home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-m32r / atomic.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  7.3 KB  |  318 lines

  1. #ifndef _ASM_M32R_ATOMIC_H
  2. #define _ASM_M32R_ATOMIC_H
  3.  
  4. /*
  5.  *  linux/include/asm-m32r/atomic.h
  6.  *
  7.  *  M32R version:
  8.  *    Copyright (C) 2001, 2002  Hitoshi Yamamoto
  9.  *    Copyright (C) 2004  Hirokazu Takata <takata at linux-m32r.org>
  10.  */
  11.  
  12. #include <asm/assembler.h>
  13. #include <asm/system.h>
  14.  
  15. /*
  16.  * Atomic operations that C can't guarantee us.  Useful for
  17.  * resource counting etc..
  18.  */
  19.  
  20. /*
  21.  * Make sure gcc doesn't try to be clever and move things around
  22.  * on us. We need to use _exactly_ the address the user gave us,
  23.  * not some alias that contains the same information.
  24.  */
  25. typedef struct { volatile int counter; } atomic_t;
  26.  
  27. #define ATOMIC_INIT(i)    { (i) }
  28.  
  29. /**
  30.  * atomic_read - read atomic variable
  31.  * @v: pointer of type atomic_t
  32.  *
  33.  * Atomically reads the value of @v.
  34.  */
  35. #define atomic_read(v)    ((v)->counter)
  36.  
  37. /**
  38.  * atomic_set - set atomic variable
  39.  * @v: pointer of type atomic_t
  40.  * @i: required value
  41.  *
  42.  * Atomically sets the value of @v to @i.
  43.  */
  44. #define atomic_set(v,i)    (((v)->counter) = (i))
  45.  
  46. /**
  47.  * atomic_add_return - add integer to atomic variable and return it
  48.  * @i: integer value to add
  49.  * @v: pointer of type atomic_t
  50.  *
  51.  * Atomically adds @i to @v and return (@i + @v).
  52.  */
  53. static __inline__ int atomic_add_return(int i, atomic_t *v)
  54. {
  55.     unsigned long flags;
  56.     int result;
  57.  
  58.     local_irq_save(flags);
  59.     __asm__ __volatile__ (
  60.         "# atomic_add_return        \n\t"
  61.         DCACHE_CLEAR("%0", "r4", "%1")
  62.         M32R_LOCK" %0, @%1;        \n\t"
  63.         "add    %0, %2;            \n\t"
  64.         M32R_UNLOCK" %0, @%1;        \n\t"
  65.         : "=&r" (result)
  66.         : "r" (&v->counter), "r" (i)
  67.         : "memory"
  68. #ifdef CONFIG_CHIP_M32700_TS1
  69.         , "r4"
  70. #endif    /* CONFIG_CHIP_M32700_TS1 */
  71.     );
  72.     local_irq_restore(flags);
  73.  
  74.     return result;
  75. }
  76.  
  77. /**
  78.  * atomic_sub_return - subtract integer from atomic variable and return it
  79.  * @i: integer value to subtract
  80.  * @v: pointer of type atomic_t
  81.  *
  82.  * Atomically subtracts @i from @v and return (@v - @i).
  83.  */
  84. static __inline__ int atomic_sub_return(int i, atomic_t *v)
  85. {
  86.     unsigned long flags;
  87.     int result;
  88.  
  89.     local_irq_save(flags);
  90.     __asm__ __volatile__ (
  91.         "# atomic_sub_return        \n\t"
  92.         DCACHE_CLEAR("%0", "r4", "%1")
  93.         M32R_LOCK" %0, @%1;        \n\t"
  94.         "sub    %0, %2;            \n\t"
  95.         M32R_UNLOCK" %0, @%1;        \n\t"
  96.         : "=&r" (result)
  97.         : "r" (&v->counter), "r" (i)
  98.         : "memory"
  99. #ifdef CONFIG_CHIP_M32700_TS1
  100.         , "r4"
  101. #endif    /* CONFIG_CHIP_M32700_TS1 */
  102.     );
  103.     local_irq_restore(flags);
  104.  
  105.     return result;
  106. }
  107.  
  108. /**
  109.  * atomic_add - add integer to atomic variable
  110.  * @i: integer value to add
  111.  * @v: pointer of type atomic_t
  112.  *
  113.  * Atomically adds @i to @v.
  114.  */
  115. #define atomic_add(i,v) ((void) atomic_add_return((i), (v)))
  116.  
  117. /**
  118.  * atomic_sub - subtract the atomic variable
  119.  * @i: integer value to subtract
  120.  * @v: pointer of type atomic_t
  121.  *
  122.  * Atomically subtracts @i from @v.
  123.  */
  124. #define atomic_sub(i,v) ((void) atomic_sub_return((i), (v)))
  125.  
  126. /**
  127.  * atomic_sub_and_test - subtract value from variable and test result
  128.  * @i: integer value to subtract
  129.  * @v: pointer of type atomic_t
  130.  *
  131.  * Atomically subtracts @i from @v and returns
  132.  * true if the result is zero, or false for all
  133.  * other cases.
  134.  */
  135. #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
  136.  
  137. /**
  138.  * atomic_inc_return - increment atomic variable and return it
  139.  * @v: pointer of type atomic_t
  140.  *
  141.  * Atomically increments @v by 1 and returns the result.
  142.  */
  143. static __inline__ int atomic_inc_return(atomic_t *v)
  144. {
  145.     unsigned long flags;
  146.     int result;
  147.  
  148.     local_irq_save(flags);
  149.     __asm__ __volatile__ (
  150.         "# atomic_inc_return        \n\t"
  151.         DCACHE_CLEAR("%0", "r4", "%1")
  152.         M32R_LOCK" %0, @%1;        \n\t"
  153.         "addi    %0, #1;            \n\t"
  154.         M32R_UNLOCK" %0, @%1;        \n\t"
  155.         : "=&r" (result)
  156.         : "r" (&v->counter)
  157.         : "memory"
  158. #ifdef CONFIG_CHIP_M32700_TS1
  159.         , "r4"
  160. #endif    /* CONFIG_CHIP_M32700_TS1 */
  161.     );
  162.     local_irq_restore(flags);
  163.  
  164.     return result;
  165. }
  166.  
  167. /**
  168.  * atomic_dec_return - decrement atomic variable and return it
  169.  * @v: pointer of type atomic_t
  170.  *
  171.  * Atomically decrements @v by 1 and returns the result.
  172.  */
  173. static __inline__ int atomic_dec_return(atomic_t *v)
  174. {
  175.     unsigned long flags;
  176.     int result;
  177.  
  178.     local_irq_save(flags);
  179.     __asm__ __volatile__ (
  180.         "# atomic_dec_return        \n\t"
  181.         DCACHE_CLEAR("%0", "r4", "%1")
  182.         M32R_LOCK" %0, @%1;        \n\t"
  183.         "addi    %0, #-1;        \n\t"
  184.         M32R_UNLOCK" %0, @%1;        \n\t"
  185.         : "=&r" (result)
  186.         : "r" (&v->counter)
  187.         : "memory"
  188. #ifdef CONFIG_CHIP_M32700_TS1
  189.         , "r4"
  190. #endif    /* CONFIG_CHIP_M32700_TS1 */
  191.     );
  192.     local_irq_restore(flags);
  193.  
  194.     return result;
  195. }
  196.  
  197. /**
  198.  * atomic_inc - increment atomic variable
  199.  * @v: pointer of type atomic_t
  200.  *
  201.  * Atomically increments @v by 1.
  202.  */
  203. #define atomic_inc(v) ((void)atomic_inc_return(v))
  204.  
  205. /**
  206.  * atomic_dec - decrement atomic variable
  207.  * @v: pointer of type atomic_t
  208.  *
  209.  * Atomically decrements @v by 1.
  210.  */
  211. #define atomic_dec(v) ((void)atomic_dec_return(v))
  212.  
  213. /**
  214.  * atomic_inc_and_test - increment and test
  215.  * @v: pointer of type atomic_t
  216.  *
  217.  * Atomically increments @v by 1
  218.  * and returns true if the result is zero, or false for all
  219.  * other cases.
  220.  */
  221. #define atomic_inc_and_test(v) (atomic_inc_return(v) == 0)
  222.  
  223. /**
  224.  * atomic_dec_and_test - decrement and test
  225.  * @v: pointer of type atomic_t
  226.  *
  227.  * Atomically decrements @v by 1 and
  228.  * returns true if the result is 0, or false for all
  229.  * other cases.
  230.  */
  231. #define atomic_dec_and_test(v) (atomic_dec_return(v) == 0)
  232.  
  233. /**
  234.  * atomic_add_negative - add and test if negative
  235.  * @v: pointer of type atomic_t
  236.  * @i: integer value to add
  237.  *
  238.  * Atomically adds @i to @v and returns true
  239.  * if the result is negative, or false when
  240.  * result is greater than or equal to zero.
  241.  */
  242. #define atomic_add_negative(i,v) (atomic_add_return((i), (v)) < 0)
  243.  
  244. #define atomic_cmpxchg(v, o, n) ((int)cmpxchg(&((v)->counter), (o), (n)))
  245. #define atomic_xchg(v, new) (xchg(&((v)->counter), new))
  246.  
  247. /**
  248.  * atomic_add_unless - add unless the number is a given value
  249.  * @v: pointer of type atomic_t
  250.  * @a: the amount to add to v...
  251.  * @u: ...unless v is equal to u.
  252.  *
  253.  * Atomically adds @a to @v, so long as it was not @u.
  254.  * Returns non-zero if @v was not @u, and zero otherwise.
  255.  */
  256. #define atomic_add_unless(v, a, u)                \
  257. ({                                \
  258.     int c, old;                        \
  259.     c = atomic_read(v);                    \
  260.     while (c != (u) && (old = atomic_cmpxchg((v), c, c + (a))) != c) \
  261.         c = old;                    \
  262.     c != (u);                        \
  263. })
  264. #define atomic_inc_not_zero(v) atomic_add_unless((v), 1, 0)
  265.  
  266. static __inline__ void atomic_clear_mask(unsigned long  mask, atomic_t *addr)
  267. {
  268.     unsigned long flags;
  269.     unsigned long tmp;
  270.  
  271.     local_irq_save(flags);
  272.     __asm__ __volatile__ (
  273.         "# atomic_clear_mask        \n\t"
  274.         DCACHE_CLEAR("%0", "r5", "%1")
  275.         M32R_LOCK" %0, @%1;        \n\t"
  276.         "and    %0, %2;            \n\t"
  277.         M32R_UNLOCK" %0, @%1;        \n\t"
  278.         : "=&r" (tmp)
  279.         : "r" (addr), "r" (~mask)
  280.         : "memory"
  281. #ifdef CONFIG_CHIP_M32700_TS1
  282.         , "r5"
  283. #endif    /* CONFIG_CHIP_M32700_TS1 */
  284.     );
  285.     local_irq_restore(flags);
  286. }
  287.  
  288. static __inline__ void atomic_set_mask(unsigned long  mask, atomic_t *addr)
  289. {
  290.     unsigned long flags;
  291.     unsigned long tmp;
  292.  
  293.     local_irq_save(flags);
  294.     __asm__ __volatile__ (
  295.         "# atomic_set_mask        \n\t"
  296.         DCACHE_CLEAR("%0", "r5", "%1")
  297.         M32R_LOCK" %0, @%1;        \n\t"
  298.         "or    %0, %2;            \n\t"
  299.         M32R_UNLOCK" %0, @%1;        \n\t"
  300.         : "=&r" (tmp)
  301.         : "r" (addr), "r" (mask)
  302.         : "memory"
  303. #ifdef CONFIG_CHIP_M32700_TS1
  304.         , "r5"
  305. #endif    /* CONFIG_CHIP_M32700_TS1 */
  306.     );
  307.     local_irq_restore(flags);
  308. }
  309.  
  310. /* Atomic operations are already serializing on m32r */
  311. #define smp_mb__before_atomic_dec()    barrier()
  312. #define smp_mb__after_atomic_dec()    barrier()
  313. #define smp_mb__before_atomic_inc()    barrier()
  314. #define smp_mb__after_atomic_inc()    barrier()
  315.  
  316. #include <asm-generic/atomic.h>
  317. #endif    /* _ASM_M32R_ATOMIC_H */
  318.