atomic.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:4k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. #ifndef __ARCH_S390_ATOMIC__
  2. #define __ARCH_S390_ATOMIC__
  3. /*
  4.  *  include/asm-s390x/atomic.h
  5.  *
  6.  *  S390 version
  7.  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  8.  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
  9.  *               Denis Joseph Barrow
  10.  *
  11.  *  Derived from "include/asm-i386/bitops.h"
  12.  *    Copyright (C) 1992, Linus Torvalds
  13.  *
  14.  */
  15. /*
  16.  * Atomic operations that C can't guarantee us.  Useful for
  17.  * resource counting etc..
  18.  * S390 uses 'Compare And Swap' for atomicity in SMP enviroment
  19.  */
  20. typedef struct { volatile int counter; } __attribute__ ((aligned (4))) atomic_t;
  21. #define ATOMIC_INIT(i)  { (i) }
  22. #define atomic_eieio()          __asm__ __volatile__ ("BCR 15,0")
  23. #define __CS_LOOP(old_val, new_val, ptr, op_val, op_string)
  24.         __asm__ __volatile__("   l     %0,0(%2)n"
  25.                              "0: lr    %1,%0n"
  26.                              op_string "  %1,%3n"
  27.                              "   cs    %0,%1,0(%2)n"
  28.                              "   jl    0b"
  29.                              : "=&d" (old_val), "=&d" (new_val)
  30.      : "a" (ptr), "d" (op_val) : "cc" );
  31. #define atomic_read(v)          ((v)->counter)
  32. #define atomic_set(v,i)         (((v)->counter) = (i))
  33. static __inline__ void atomic_add(int i, atomic_t *v)
  34. {
  35. int old_val, new_val;
  36. __CS_LOOP(old_val, new_val, v, i, "ar");
  37. }
  38. static __inline__ int atomic_add_return (int i, atomic_t *v)
  39. {
  40. int old_val, new_val;
  41. __CS_LOOP(old_val, new_val, v, i, "ar");
  42. return new_val;
  43. }
  44. static __inline__ int atomic_add_negative(int i, atomic_t *v)
  45. {
  46. int old_val, new_val;
  47.         __CS_LOOP(old_val, new_val, v, i, "ar");
  48.         return new_val < 0;
  49. }
  50. static __inline__ void atomic_sub(int i, atomic_t *v)
  51. {
  52. int old_val, new_val;
  53. __CS_LOOP(old_val, new_val, v, i, "sr");
  54. }
  55. static __inline__ void atomic_inc(volatile atomic_t *v)
  56. {
  57. int old_val, new_val;
  58. __CS_LOOP(old_val, new_val, v, 1, "ar");
  59. }
  60. static __inline__ int atomic_inc_return(volatile atomic_t *v)
  61. {
  62. int old_val, new_val;
  63. __CS_LOOP(old_val, new_val, v, 1, "ar");
  64.         return new_val;
  65. }
  66. static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
  67. {
  68. int old_val, new_val;
  69. __CS_LOOP(old_val, new_val, v, 1, "ar");
  70. return new_val != 0;
  71. }
  72. static __inline__ void atomic_dec(volatile atomic_t *v)
  73. {
  74. int old_val, new_val;
  75. __CS_LOOP(old_val, new_val, v, 1, "sr");
  76. }
  77. static __inline__ int atomic_dec_return(volatile atomic_t *v)
  78. {
  79. int old_val, new_val;
  80. __CS_LOOP(old_val, new_val, v, 1, "sr");
  81. return new_val;
  82. }
  83. static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
  84. {
  85. int old_val, new_val;
  86. __CS_LOOP(old_val, new_val, v, 1, "sr");
  87.         return new_val == 0;
  88. }
  89. static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v)
  90. {
  91. int old_val, new_val;
  92. __CS_LOOP(old_val, new_val, v, ~mask, "nr");
  93. }
  94. static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v)
  95. {
  96. int old_val, new_val;
  97. __CS_LOOP(old_val, new_val, v, mask, "or");
  98. }
  99. /*
  100.   returns 0  if expected_oldval==value in *v ( swap was successful )
  101.   returns 1  if unsuccessful.
  102. */
  103. static __inline__ int
  104. atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)
  105. {
  106.         int retval;
  107.         __asm__ __volatile__(
  108.                 "  lr   0,%2n"
  109.                 "  cs   0,%3,0(%1)n"
  110.                 "  ipm  %0n"
  111.                 "  srl  %0,28n"
  112.                 "0:"
  113.                 : "=&d" (retval)
  114.                 : "a" (v), "d" (expected_oldval) , "d" (new_val)
  115.                 : "0", "cc");
  116.         return retval;
  117. }
  118. /*
  119.   Spin till *v = expected_oldval then swap with newval.
  120.  */
  121. static __inline__ void
  122. atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v)
  123. {
  124.         __asm__ __volatile__(
  125.                 "0: lr  0,%1n"
  126.                 "   cs  0,%2,0(%0)n"
  127.                 "   jl  0bn"
  128.                 : : "a" (v), "d" (expected_oldval) , "d" (new_val)
  129.                 : "cc", "0" );
  130. }
  131. #define atomic_compare_and_swap_debug(where,from,to) 
  132. if (atomic_compare_and_swap ((from), (to), (where))) {
  133. printk (KERN_WARNING"%s/%d atomic counter:%s couldn't be changed from %d(%s) to %d(%s), was %dn",
  134. __FILE__,__LINE__,#where,(from),#from,(to),#to,atomic_read (where));
  135.         atomic_set(where,(to));
  136. }
  137. #define smp_mb__before_atomic_dec() smp_mb()
  138. #define smp_mb__after_atomic_dec() smp_mb()
  139. #define smp_mb__before_atomic_inc() smp_mb()
  140. #define smp_mb__after_atomic_inc() smp_mb()
  141. #endif                                 /* __ARCH_S390_ATOMIC __            */