Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. #ifndef _ASM_X86_ATOMIC_32_H
  2. #define _ASM_X86_ATOMIC_32_H
  3.  
  4. #include <linux/compiler.h>
  5. #include <linux/types.h>
  6. //#include <asm/processor.h>
  7. #include <asm/cmpxchg.h>
  8.  
  9. /*
  10.  * Atomic operations that C can't guarantee us.  Useful for
  11.  * resource counting etc..
  12.  */
  13.  
  14. #define ATOMIC_INIT(i)  { (i) }
  15.  
  16. /**
  17.  * atomic_read - read atomic variable
  18.  * @v: pointer of type atomic_t
  19.  *
  20.  * Atomically reads the value of @v.
  21.  */
  22. static inline int atomic_read(const atomic_t *v)
  23. {
  24.         return v->counter;
  25. }
  26.  
  27. /**
  28.  * atomic_set - set atomic variable
  29.  * @v: pointer of type atomic_t
  30.  * @i: required value
  31.  *
  32.  * Atomically sets the value of @v to @i.
  33.  */
  34. static inline void atomic_set(atomic_t *v, int i)
  35. {
  36.         v->counter = i;
  37. }
  38.  
  39. /**
  40.  * atomic_add - add integer to atomic variable
  41.  * @i: integer value to add
  42.  * @v: pointer of type atomic_t
  43.  *
  44.  * Atomically adds @i to @v.
  45.  */
  46. static inline void atomic_add(int i, atomic_t *v)
  47. {
  48.         asm volatile(LOCK_PREFIX "addl %1,%0"
  49.                      : "+m" (v->counter)
  50.                      : "ir" (i));
  51. }
  52.  
  53. /**
  54.  * atomic_sub - subtract integer from atomic variable
  55.  * @i: integer value to subtract
  56.  * @v: pointer of type atomic_t
  57.  *
  58.  * Atomically subtracts @i from @v.
  59.  */
  60. static inline void atomic_sub(int i, atomic_t *v)
  61. {
  62.         asm volatile(LOCK_PREFIX "subl %1,%0"
  63.                      : "+m" (v->counter)
  64.                      : "ir" (i));
  65. }
  66.  
  67. /**
  68.  * atomic_sub_and_test - subtract value from variable and test result
  69.  * @i: integer value to subtract
  70.  * @v: pointer of type atomic_t
  71.  *
  72.  * Atomically subtracts @i from @v and returns
  73.  * true if the result is zero, or false for all
  74.  * other cases.
  75.  */
  76. static inline int atomic_sub_and_test(int i, atomic_t *v)
  77. {
  78.         unsigned char c;
  79.  
  80.         asm volatile(LOCK_PREFIX "subl %2,%0; sete %1"
  81.                      : "+m" (v->counter), "=qm" (c)
  82.                      : "ir" (i) : "memory");
  83.         return c;
  84. }
  85.  
  86. /**
  87.  * atomic_inc - increment atomic variable
  88.  * @v: pointer of type atomic_t
  89.  *
  90.  * Atomically increments @v by 1.
  91.  */
  92. static inline void atomic_inc(atomic_t *v)
  93. {
  94.         asm volatile(LOCK_PREFIX "incl %0"
  95.                      : "+m" (v->counter));
  96. }
  97.  
  98. /**
  99.  * atomic_dec - decrement atomic variable
  100.  * @v: pointer of type atomic_t
  101.  *
  102.  * Atomically decrements @v by 1.
  103.  */
  104. static inline void atomic_dec(atomic_t *v)
  105. {
  106.         asm volatile(LOCK_PREFIX "decl %0"
  107.                      : "+m" (v->counter));
  108. }
  109.  
  110. /**
  111.  * atomic_dec_and_test - decrement and test
  112.  * @v: pointer of type atomic_t
  113.  *
  114.  * Atomically decrements @v by 1 and
  115.  * returns true if the result is 0, or false for all other
  116.  * cases.
  117.  */
  118. static inline int atomic_dec_and_test(atomic_t *v)
  119. {
  120.         unsigned char c;
  121.  
  122.         asm volatile(LOCK_PREFIX "decl %0; sete %1"
  123.                      : "+m" (v->counter), "=qm" (c)
  124.                      : : "memory");
  125.         return c != 0;
  126. }
  127.  
  128. /**
  129.  * atomic_inc_and_test - increment and test
  130.  * @v: pointer of type atomic_t
  131.  *
  132.  * Atomically increments @v by 1
  133.  * and returns true if the result is zero, or false for all
  134.  * other cases.
  135.  */
  136. static inline int atomic_inc_and_test(atomic_t *v)
  137. {
  138.         unsigned char c;
  139.  
  140.         asm volatile(LOCK_PREFIX "incl %0; sete %1"
  141.                      : "+m" (v->counter), "=qm" (c)
  142.                      : : "memory");
  143.         return c != 0;
  144. }
  145.  
  146. /**
  147.  * atomic_add_negative - add and test if negative
  148.  * @v: pointer of type atomic_t
  149.  * @i: integer value to add
  150.  *
  151.  * Atomically adds @i to @v and returns true
  152.  * if the result is negative, or false when
  153.  * result is greater than or equal to zero.
  154.  */
  155. static inline int atomic_add_negative(int i, atomic_t *v)
  156. {
  157.         unsigned char c;
  158.  
  159.         asm volatile(LOCK_PREFIX "addl %2,%0; sets %1"
  160.                      : "+m" (v->counter), "=qm" (c)
  161.                      : "ir" (i) : "memory");
  162.         return c;
  163. }
  164.  
  165. /**
  166.  * atomic_add_return - add integer and return
  167.  * @v: pointer of type atomic_t
  168.  * @i: integer value to add
  169.  *
  170.  * Atomically adds @i to @v and returns @i + @v
  171.  */
  172. static inline int atomic_add_return(int i, atomic_t *v)
  173. {
  174.         int __i;
  175. #ifdef CONFIG_M386
  176.         unsigned long flags;
  177.         if (unlikely(boot_cpu_data.x86 <= 3))
  178.                 goto no_xadd;
  179. #endif
  180.         /* Modern 486+ processor */
  181.         __i = i;
  182.         asm volatile(LOCK_PREFIX "xaddl %0, %1"
  183.                      : "+r" (i), "+m" (v->counter)
  184.                      : : "memory");
  185.         return i + __i;
  186.  
  187. #ifdef CONFIG_M386
  188. no_xadd: /* Legacy 386 processor */
  189.         local_irq_save(flags);
  190.         __i = atomic_read(v);
  191.         atomic_set(v, i + __i);
  192.         local_irq_restore(flags);
  193.         return i + __i;
  194. #endif
  195. }
  196.  
  197. /**
  198.  * atomic_sub_return - subtract integer and return
  199.  * @v: pointer of type atomic_t
  200.  * @i: integer value to subtract
  201.  *
  202.  * Atomically subtracts @i from @v and returns @v - @i
  203.  */
  204. static inline int atomic_sub_return(int i, atomic_t *v)
  205. {
  206.         return atomic_add_return(-i, v);
  207. }
  208.  
  209. static inline int atomic_cmpxchg(atomic_t *v, int old, int new)
  210. {
  211.         return cmpxchg(&v->counter, old, new);
  212. }
  213.  
  214. static inline int atomic_xchg(atomic_t *v, int new)
  215. {
  216.         return xchg(&v->counter, new);
  217. }
  218.  
  219. /**
  220.  * atomic_add_unless - add unless the number is already a given value
  221.  * @v: pointer of type atomic_t
  222.  * @a: the amount to add to v...
  223.  * @u: ...unless v is equal to u.
  224.  *
  225.  * Atomically adds @a to @v, so long as @v was not already @u.
  226.  * Returns non-zero if @v was not @u, and zero otherwise.
  227.  */
  228. static inline int atomic_add_unless(atomic_t *v, int a, int u)
  229. {
  230.         int c, old;
  231.         c = atomic_read(v);
  232.         for (;;) {
  233.                 if (unlikely(c == (u)))
  234.                         break;
  235.                 old = atomic_cmpxchg((v), c, c + (a));
  236.                 if (likely(old == c))
  237.                         break;
  238.                 c = old;
  239.         }
  240.         return c != (u);
  241. }
  242.  
  243. #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
  244.  
  245. #define atomic_inc_return(v)  (atomic_add_return(1, v))
  246. #define atomic_dec_return(v)  (atomic_sub_return(1, v))
  247.  
  248. /* These are x86-specific, used by some header files */
  249. #define atomic_clear_mask(mask, addr)                           \
  250.         asm volatile(LOCK_PREFIX "andl %0,%1"                   \
  251.                      : : "r" (~(mask)), "m" (*(addr)) : "memory")
  252.  
  253. #define atomic_set_mask(mask, addr)                             \
  254.         asm volatile(LOCK_PREFIX "orl %0,%1"                            \
  255.                      : : "r" (mask), "m" (*(addr)) : "memory")
  256.  
  257. /* Atomic operations are already serializing on x86 */
  258. #define smp_mb__before_atomic_dec()     barrier()
  259. #define smp_mb__after_atomic_dec()      barrier()
  260. #define smp_mb__before_atomic_inc()     barrier()
  261. #define smp_mb__after_atomic_inc()      barrier()
  262.  
  263. /* An 64bit atomic type */
  264.  
  265. typedef struct {
  266.         u64 __aligned(8) counter;
  267. } atomic64_t;
  268.  
  269. #define ATOMIC64_INIT(val)      { (val) }
  270.  
  271. extern u64 atomic64_cmpxchg(atomic64_t *ptr, u64 old_val, u64 new_val);
  272.  
  273. /**
  274.  * atomic64_xchg - xchg atomic64 variable
  275.  * @ptr:      pointer to type atomic64_t
  276.  * @new_val:  value to assign
  277.  *
  278.  * Atomically xchgs the value of @ptr to @new_val and returns
  279.  * the old value.
  280.  */
  281. extern u64 atomic64_xchg(atomic64_t *ptr, u64 new_val);
  282.  
  283. /**
  284.  * atomic64_set - set atomic64 variable
  285.  * @ptr:      pointer to type atomic64_t
  286.  * @new_val:  value to assign
  287.  *
  288.  * Atomically sets the value of @ptr to @new_val.
  289.  */
  290. extern void atomic64_set(atomic64_t *ptr, u64 new_val);
  291.  
  292. /**
  293.  * atomic64_read - read atomic64 variable
  294.  * @ptr:      pointer to type atomic64_t
  295.  *
  296.  * Atomically reads the value of @ptr and returns it.
  297.  */
  298. static inline u64 atomic64_read(atomic64_t *ptr)
  299. {
  300.         u64 res;
  301.  
  302.         /*
  303.          * Note, we inline this atomic64_t primitive because
  304.          * it only clobbers EAX/EDX and leaves the others
  305.          * untouched. We also (somewhat subtly) rely on the
  306.          * fact that cmpxchg8b returns the current 64-bit value
  307.          * of the memory location we are touching:
  308.          */
  309.         asm volatile(
  310.                 "mov %%ebx, %%eax\n\t"
  311.                 "mov %%ecx, %%edx\n\t"
  312.                 LOCK_PREFIX "cmpxchg8b %1\n"
  313.                         : "=&A" (res)
  314.                         : "m" (*ptr)
  315.                 );
  316.  
  317.         return res;
  318. }
  319.  
  320. extern u64 atomic64_read(atomic64_t *ptr);
  321.  
  322. /**
  323.  * atomic64_add_return - add and return
  324.  * @delta: integer value to add
  325.  * @ptr:   pointer to type atomic64_t
  326.  *
  327.  * Atomically adds @delta to @ptr and returns @delta + *@ptr
  328.  */
  329. extern u64 atomic64_add_return(u64 delta, atomic64_t *ptr);
  330.  
  331. /*
  332.  * Other variants with different arithmetic operators:
  333.  */
  334. extern u64 atomic64_sub_return(u64 delta, atomic64_t *ptr);
  335. extern u64 atomic64_inc_return(atomic64_t *ptr);
  336. extern u64 atomic64_dec_return(atomic64_t *ptr);
  337.  
  338. /**
  339.  * atomic64_add - add integer to atomic64 variable
  340.  * @delta: integer value to add
  341.  * @ptr:   pointer to type atomic64_t
  342.  *
  343.  * Atomically adds @delta to @ptr.
  344.  */
  345. extern void atomic64_add(u64 delta, atomic64_t *ptr);
  346.  
  347. /**
  348.  * atomic64_sub - subtract the atomic64 variable
  349.  * @delta: integer value to subtract
  350.  * @ptr:   pointer to type atomic64_t
  351.  *
  352.  * Atomically subtracts @delta from @ptr.
  353.  */
  354. extern void atomic64_sub(u64 delta, atomic64_t *ptr);
  355.  
  356. /**
  357.  * atomic64_sub_and_test - subtract value from variable and test result
  358.  * @delta: integer value to subtract
  359.  * @ptr:   pointer to type atomic64_t
  360.  *
  361.  * Atomically subtracts @delta from @ptr and returns
  362.  * true if the result is zero, or false for all
  363.  * other cases.
  364.  */
  365. extern int atomic64_sub_and_test(u64 delta, atomic64_t *ptr);
  366.  
  367. /**
  368.  * atomic64_inc - increment atomic64 variable
  369.  * @ptr: pointer to type atomic64_t
  370.  *
  371.  * Atomically increments @ptr by 1.
  372.  */
  373. extern void atomic64_inc(atomic64_t *ptr);
  374.  
  375. /**
  376.  * atomic64_dec - decrement atomic64 variable
  377.  * @ptr: pointer to type atomic64_t
  378.  *
  379.  * Atomically decrements @ptr by 1.
  380.  */
  381. extern void atomic64_dec(atomic64_t *ptr);
  382.  
  383. /**
  384.  * atomic64_dec_and_test - decrement and test
  385.  * @ptr: pointer to type atomic64_t
  386.  *
  387.  * Atomically decrements @ptr by 1 and
  388.  * returns true if the result is 0, or false for all other
  389.  * cases.
  390.  */
  391. extern int atomic64_dec_and_test(atomic64_t *ptr);
  392.  
  393. /**
  394.  * atomic64_inc_and_test - increment and test
  395.  * @ptr: pointer to type atomic64_t
  396.  *
  397.  * Atomically increments @ptr by 1
  398.  * and returns true if the result is zero, or false for all
  399.  * other cases.
  400.  */
  401. extern int atomic64_inc_and_test(atomic64_t *ptr);
  402.  
  403. /**
  404.  * atomic64_add_negative - add and test if negative
  405.  * @delta: integer value to add
  406.  * @ptr:   pointer to type atomic64_t
  407.  *
  408.  * Atomically adds @delta to @ptr and returns true
  409.  * if the result is negative, or false when
  410.  * result is greater than or equal to zero.
  411.  */
  412. extern int atomic64_add_negative(u64 delta, atomic64_t *ptr);
  413.  
  414. #include <asm-generic/atomic-long.h>
  415. #endif /* _ASM_X86_ATOMIC_32_H */
  416.