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

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * Atomic operations that C can't guarantee us.  Useful for
  3.  * resource counting etc..
  4.  *
  5.  * But use these as seldom as possible since they are much more slower
  6.  * than regular operations.
  7.  *
  8.  * This file is subject to the terms and conditions of the GNU General Public
  9.  * License.  See the file "COPYING" in the main directory of this archive
  10.  * for more details.
  11.  *
  12.  * Copyright (C) 1996, 1997, 2000 by Ralf Baechle
  13.  */
  14. #ifndef __ASM_ATOMIC_H
  15. #define __ASM_ATOMIC_H
  16. #include <linux/config.h>
  17. typedef struct { volatile int counter; } atomic_t;
  18. #ifdef __KERNEL__
  19. #define ATOMIC_INIT(i)    { (i) }
  20. /*
  21.  * atomic_read - read atomic variable
  22.  * @v: pointer of type atomic_t
  23.  *
  24.  * Atomically reads the value of @v.  Note that the guaranteed
  25.  * useful range of an atomic_t is only 24 bits.
  26.  */
  27. #define atomic_read(v) ((v)->counter)
  28. /*
  29.  * atomic_set - set atomic variable
  30.  * @v: pointer of type atomic_t
  31.  * @i: required value
  32.  *
  33.  * Atomically sets the value of @v to @i.  Note that the guaranteed
  34.  * useful range of an atomic_t is only 24 bits.
  35.  */
  36. #define atomic_set(v,i) ((v)->counter = (i))
  37. #ifndef CONFIG_CPU_HAS_LLSC
  38. #include <asm/system.h>
  39. /*
  40.  * The MIPS I implementation is only atomic with respect to
  41.  * interrupts.  R3000 based multiprocessor machines are rare anyway ...
  42.  *
  43.  * atomic_add - add integer to atomic variable
  44.  * @i: integer value to add
  45.  * @v: pointer of type atomic_t
  46.  *
  47.  * Atomically adds @i to @v.  Note that the guaranteed useful range
  48.  * of an atomic_t is only 24 bits.
  49.  */
  50. extern __inline__ void atomic_add(int i, atomic_t * v)
  51. {
  52. unsigned long flags;
  53. save_and_cli(flags);
  54. v->counter += i;
  55. restore_flags(flags);
  56. }
  57. /*
  58.  * atomic_sub - subtract the atomic variable
  59.  * @i: integer value to subtract
  60.  * @v: pointer of type atomic_t
  61.  *
  62.  * Atomically subtracts @i from @v.  Note that the guaranteed
  63.  * useful range of an atomic_t is only 24 bits.
  64.  */
  65. extern __inline__ void atomic_sub(int i, atomic_t * v)
  66. {
  67. unsigned long flags;
  68. save_and_cli(flags);
  69. v->counter -= i;
  70. restore_flags(flags);
  71. }
  72. extern __inline__ int atomic_add_return(int i, atomic_t * v)
  73. {
  74. unsigned long flags;
  75. int temp;
  76. save_and_cli(flags);
  77. temp = v->counter;
  78. temp += i;
  79. v->counter = temp;
  80. restore_flags(flags);
  81. return temp;
  82. }
  83. extern __inline__ int atomic_sub_return(int i, atomic_t * v)
  84. {
  85. unsigned long flags;
  86. int temp;
  87. save_and_cli(flags);
  88. temp = v->counter;
  89. temp -= i;
  90. v->counter = temp;
  91. restore_flags(flags);
  92. return temp;
  93. }
  94. #else
  95. /*
  96.  * ... while for MIPS II and better we can use ll/sc instruction.  This
  97.  * implementation is SMP safe ...
  98.  */
  99. /*
  100.  * atomic_add - add integer to atomic variable
  101.  * @i: integer value to add
  102.  * @v: pointer of type atomic_t
  103.  *
  104.  * Atomically adds @i to @v.  Note that the guaranteed useful range
  105.  * of an atomic_t is only 24 bits.
  106.  */
  107. extern __inline__ void atomic_add(int i, atomic_t * v)
  108. {
  109. unsigned long temp;
  110. __asm__ __volatile__(
  111. "1:   ll      %0, %1      # atomic_addn"
  112. "     addu    %0, %2                  n"
  113. "     sc      %0, %1                  n"
  114. "     beqz    %0, 1b                  n"
  115. : "=&r" (temp), "=m" (v->counter)
  116. : "Ir" (i), "m" (v->counter));
  117. }
  118. /*
  119.  * atomic_sub - subtract the atomic variable
  120.  * @i: integer value to subtract
  121.  * @v: pointer of type atomic_t
  122.  *
  123.  * Atomically subtracts @i from @v.  Note that the guaranteed
  124.  * useful range of an atomic_t is only 24 bits.
  125.  */
  126. extern __inline__ void atomic_sub(int i, atomic_t * v)
  127. {
  128. unsigned long temp;
  129. __asm__ __volatile__(
  130. "1:   ll      %0, %1      # atomic_subn"
  131. "     subu    %0, %2                  n"
  132. "     sc      %0, %1                  n"
  133. "     beqz    %0, 1b                  n"
  134. : "=&r" (temp), "=m" (v->counter)
  135. : "Ir" (i), "m" (v->counter));
  136. }
  137. /*
  138.  * Same as above, but return the result value
  139.  */
  140. extern __inline__ int atomic_add_return(int i, atomic_t * v)
  141. {
  142. unsigned long temp, result;
  143. __asm__ __volatile__(
  144. ".set push               # atomic_add_returnn"
  145. ".set noreorder                             n"
  146. "1:   ll      %1, %2                        n"
  147. "     addu    %0, %1, %3                    n"
  148. "     sc      %0, %2                        n"
  149. "     beqz    %0, 1b                        n"
  150. "     addu    %0, %1, %3                    n"
  151. "     sync                                  n"
  152. ".set pop                                   n"
  153. : "=&r" (result), "=&r" (temp), "=m" (v->counter)
  154. : "Ir" (i), "m" (v->counter)
  155. : "memory");
  156. return result;
  157. }
  158. extern __inline__ int atomic_sub_return(int i, atomic_t * v)
  159. {
  160. unsigned long temp, result;
  161. __asm__ __volatile__(
  162. ".set push                                   n"
  163. ".set noreorder           # atomic_sub_returnn"
  164. "1:   ll    %1, %2                           n"
  165. "     subu  %0, %1, %3                       n"
  166. "     sc    %0, %2                           n"
  167. "     beqz  %0, 1b                           n"
  168. "     subu  %0, %1, %3                       n"
  169. "     sync                                   n"
  170. ".set pop                                    n"
  171. : "=&r" (result), "=&r" (temp), "=m" (v->counter)
  172. : "Ir" (i), "m" (v->counter)
  173. : "memory");
  174. return result;
  175. }
  176. #endif
  177. #define atomic_dec_return(v) atomic_sub_return(1,(v))
  178. #define atomic_inc_return(v) atomic_add_return(1,(v))
  179. /*
  180.  * atomic_sub_and_test - subtract value from variable and test result
  181.  * @i: integer value to subtract
  182.  * @v: pointer of type atomic_t
  183.  *
  184.  * Atomically subtracts @i from @v and returns
  185.  * true if the result is zero, or false for all
  186.  * other cases.  Note that the guaranteed
  187.  * useful range of an atomic_t is only 24 bits.
  188.  */
  189. #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
  190. /*
  191.  * atomic_inc_and_test - increment and test
  192.  * @v: pointer of type atomic_t
  193.  *
  194.  * Atomically increments @v by 1
  195.  * and returns true if the result is zero, or false for all
  196.  * other cases.  Note that the guaranteed
  197.  * useful range of an atomic_t is only 24 bits.
  198.  */
  199. #define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0)
  200. /*
  201.  * atomic_dec_and_test - decrement by 1 and test
  202.  * @v: pointer of type atomic_t
  203.  *
  204.  * Atomically decrements @v by 1 and
  205.  * returns true if the result is 0, or false for all other
  206.  * cases.  Note that the guaranteed
  207.  * useful range of an atomic_t is only 24 bits.
  208.  */
  209. #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
  210. /*
  211.  * atomic_inc - increment atomic variable
  212.  * @v: pointer of type atomic_t
  213.  *
  214.  * Atomically increments @v by 1.  Note that the guaranteed
  215.  * useful range of an atomic_t is only 24 bits.
  216.  */
  217. #define atomic_inc(v) atomic_add(1,(v))
  218. /*
  219.  * atomic_dec - decrement and test
  220.  * @v: pointer of type atomic_t
  221.  *
  222.  * Atomically decrements @v by 1.  Note that the guaranteed
  223.  * useful range of an atomic_t is only 24 bits.
  224.  */
  225. #define atomic_dec(v) atomic_sub(1,(v))
  226. /*
  227.  * atomic_add_negative - add and test if negative
  228.  * @v: pointer of type atomic_t
  229.  * @i: integer value to add
  230.  *
  231.  * Atomically adds @i to @v and returns true
  232.  * if the result is negative, or false when
  233.  * result is greater than or equal to zero.  Note that the guaranteed
  234.  * useful range of an atomic_t is only 24 bits.
  235.  *
  236.  * Currently not implemented for MIPS.
  237.  */
  238. /* Atomic operations are already serializing */
  239. #define smp_mb__before_atomic_dec() smp_mb()
  240. #define smp_mb__after_atomic_dec() smp_mb()
  241. #define smp_mb__before_atomic_inc() smp_mb()
  242. #define smp_mb__after_atomic_inc() smp_mb()
  243. #endif /* defined(__KERNEL__) */
  244. #endif /* __ASM_ATOMIC_H */