home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / SLAX 6.0.8 / slax-6.0.8.iso / slax / base / 006-devel.lzm / usr / include / alsa / iatomic.h < prev    next >
Encoding:
C/C++ Source or Header  |  2008-09-18  |  28.3 KB  |  1,176 lines

  1. #ifndef __ALSA_IATOMIC_H
  2. #define __ALSA_IATOMIC_H
  3.  
  4. #if defined(__i386__) || defined(__x86_64__)
  5.  
  6. /*
  7.  * Atomic operations that C can't guarantee us.  Useful for
  8.  * resource counting etc..
  9.  */
  10.  
  11. #define ATOMIC_SMP_LOCK "lock ; "
  12.  
  13. /*
  14.  * Make sure gcc doesn't try to be clever and move things around
  15.  * on us. We need to use _exactly_ the address the user gave us,
  16.  * not some alias that contains the same information.
  17.  */
  18. typedef struct { volatile int counter; } atomic_t;
  19.  
  20. #define ATOMIC_INIT(i)    { (i) }
  21.  
  22. /**
  23.  * atomic_read - read atomic variable
  24.  * @v: pointer of type atomic_t
  25.  * 
  26.  * Atomically reads the value of @v.  Note that the guaranteed
  27.  * useful range of an atomic_t is only 24 bits.
  28.  */ 
  29. #define atomic_read(v)        ((v)->counter)
  30.  
  31. /**
  32.  * atomic_set - set atomic variable
  33.  * @v: pointer of type atomic_t
  34.  * @i: required value
  35.  * 
  36.  * Atomically sets the value of @v to @i.  Note that the guaranteed
  37.  * useful range of an atomic_t is only 24 bits.
  38.  */ 
  39. #define atomic_set(v,i)        (((v)->counter) = (i))
  40.  
  41. /**
  42.  * atomic_add - add integer to atomic variable
  43.  * @i: integer value to add
  44.  * @v: pointer of type atomic_t
  45.  * 
  46.  * Atomically adds @i to @v.  Note that the guaranteed useful range
  47.  * of an atomic_t is only 24 bits.
  48.  */
  49. static __inline__ void atomic_add(int i, atomic_t *v)
  50. {
  51.     __asm__ __volatile__(
  52.         ATOMIC_SMP_LOCK "addl %1,%0"
  53.         :"=m" (v->counter)
  54.         :"ir" (i), "m" (v->counter));
  55. }
  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. static __inline__ void atomic_sub(int i, atomic_t *v)
  66. {
  67.     __asm__ __volatile__(
  68.         ATOMIC_SMP_LOCK "subl %1,%0"
  69.         :"=m" (v->counter)
  70.         :"ir" (i), "m" (v->counter));
  71. }
  72.  
  73. /**
  74.  * atomic_sub_and_test - subtract value from variable and test result
  75.  * @i: integer value to subtract
  76.  * @v: pointer of type atomic_t
  77.  * 
  78.  * Atomically subtracts @i from @v and returns
  79.  * true if the result is zero, or false for all
  80.  * other cases.  Note that the guaranteed
  81.  * useful range of an atomic_t is only 24 bits.
  82.  */
  83. static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
  84. {
  85.     unsigned char c;
  86.  
  87.     __asm__ __volatile__(
  88.         ATOMIC_SMP_LOCK "subl %2,%0; sete %1"
  89.         :"=m" (v->counter), "=qm" (c)
  90.         :"ir" (i), "m" (v->counter) : "memory");
  91.     return c;
  92. }
  93.  
  94. /**
  95.  * atomic_inc - increment atomic variable
  96.  * @v: pointer of type atomic_t
  97.  * 
  98.  * Atomically increments @v by 1.  Note that the guaranteed
  99.  * useful range of an atomic_t is only 24 bits.
  100.  */ 
  101. static __inline__ void atomic_inc(atomic_t *v)
  102. {
  103.     __asm__ __volatile__(
  104.         ATOMIC_SMP_LOCK "incl %0"
  105.         :"=m" (v->counter)
  106.         :"m" (v->counter));
  107. }
  108.  
  109. /**
  110.  * atomic_dec - decrement atomic variable
  111.  * @v: pointer of type atomic_t
  112.  * 
  113.  * Atomically decrements @v by 1.  Note that the guaranteed
  114.  * useful range of an atomic_t is only 24 bits.
  115.  */ 
  116. static __inline__ void atomic_dec(atomic_t *v)
  117. {
  118.     __asm__ __volatile__(
  119.         ATOMIC_SMP_LOCK "decl %0"
  120.         :"=m" (v->counter)
  121.         :"m" (v->counter));
  122. }
  123.  
  124. /**
  125.  * atomic_dec_and_test - decrement and test
  126.  * @v: pointer of type atomic_t
  127.  * 
  128.  * Atomically decrements @v by 1 and
  129.  * returns true if the result is 0, or false for all other
  130.  * cases.  Note that the guaranteed
  131.  * useful range of an atomic_t is only 24 bits.
  132.  */ 
  133. static __inline__ int atomic_dec_and_test(atomic_t *v)
  134. {
  135.     unsigned char c;
  136.  
  137.     __asm__ __volatile__(
  138.         ATOMIC_SMP_LOCK "decl %0; sete %1"
  139.         :"=m" (v->counter), "=qm" (c)
  140.         :"m" (v->counter) : "memory");
  141.     return c != 0;
  142. }
  143.  
  144. /**
  145.  * atomic_inc_and_test - increment and test 
  146.  * @v: pointer of type atomic_t
  147.  * 
  148.  * Atomically increments @v by 1
  149.  * and returns true if the result is zero, or false for all
  150.  * other cases.  Note that the guaranteed
  151.  * useful range of an atomic_t is only 24 bits.
  152.  */ 
  153. static __inline__ int atomic_inc_and_test(atomic_t *v)
  154. {
  155.     unsigned char c;
  156.  
  157.     __asm__ __volatile__(
  158.         ATOMIC_SMP_LOCK "incl %0; sete %1"
  159.         :"=m" (v->counter), "=qm" (c)
  160.         :"m" (v->counter) : "memory");
  161.     return c != 0;
  162. }
  163.  
  164. /**
  165.  * atomic_add_negative - add and test if negative
  166.  * @v: pointer of type atomic_t
  167.  * @i: integer value to add
  168.  * 
  169.  * Atomically adds @i to @v and returns true
  170.  * if the result is negative, or false when
  171.  * result is greater than or equal to zero.  Note that the guaranteed
  172.  * useful range of an atomic_t is only 24 bits.
  173.  */ 
  174. static __inline__ int atomic_add_negative(int i, atomic_t *v)
  175. {
  176.     unsigned char c;
  177.  
  178.     __asm__ __volatile__(
  179.         ATOMIC_SMP_LOCK "addl %2,%0; sets %1"
  180.         :"=m" (v->counter), "=qm" (c)
  181.         :"ir" (i), "m" (v->counter) : "memory");
  182.     return c;
  183. }
  184.  
  185. /* These are x86-specific, used by some header files */
  186. #define atomic_clear_mask(mask, addr) \
  187. __asm__ __volatile__(ATOMIC_SMP_LOCK "andl %0,%1" \
  188. : : "r" (~(mask)),"m" (*addr) : "memory")
  189.  
  190. #define atomic_set_mask(mask, addr) \
  191. __asm__ __volatile__(ATOMIC_SMP_LOCK "orl %0,%1" \
  192. : : "r" (mask),"m" (*addr) : "memory")
  193.  
  194. /*
  195.  * Force strict CPU ordering.
  196.  * And yes, this is required on UP too when we're talking
  197.  * to devices.
  198.  *
  199.  * For now, "wmb()" doesn't actually do anything, as all
  200.  * Intel CPU's follow what Intel calls a *Processor Order*,
  201.  * in which all writes are seen in the program order even
  202.  * outside the CPU.
  203.  *
  204.  * I expect future Intel CPU's to have a weaker ordering,
  205.  * but I'd also expect them to finally get their act together
  206.  * and add some real memory barriers if so.
  207.  */
  208.  
  209. #ifdef __i386__
  210. #define mb()     __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
  211. #define rmb()    mb()
  212. #define wmb()    __asm__ __volatile__ ("": : :"memory")
  213. #else
  214. #define mb()     asm volatile("mfence":::"memory")
  215. #define rmb()    asm volatile("lfence":::"memory")
  216. #define wmb()    asm volatile("sfence":::"memory")
  217. #endif
  218.  
  219. #undef ATOMIC_SMP_LOCK
  220.  
  221. #define IATOMIC_DEFINED        1
  222.  
  223. #endif /* __i386__ */
  224.  
  225. #ifdef __ia64__
  226.  
  227. /*
  228.  * On IA-64, counter must always be volatile to ensure that that the
  229.  * memory accesses are ordered.
  230.  */
  231. typedef struct { volatile int counter; } atomic_t;
  232.  
  233. #define ATOMIC_INIT(i)        ((atomic_t) { (i) })
  234.  
  235. #define atomic_read(v)        ((v)->counter)
  236. #define atomic_set(v,i)        (((v)->counter) = (i))
  237.  
  238. /* stripped version - we need only 4byte version */
  239. #define ia64_cmpxchg(sem,ptr,old,new,size) \
  240. ({ \
  241.     __typeof__(ptr) _p_ = (ptr); \
  242.     __typeof__(new) _n_ = (new); \
  243.     unsigned long _o_, _r_; \
  244.     _o_ = (unsigned int) (long) (old); \
  245.     __asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO"(_o_)); \
  246.     __asm__ __volatile__ ("cmpxchg4."sem" %0=[%1],%2,ar.ccv" \
  247.                   : "=r"(_r_) : "r"(_p_), "r"(_n_) : "memory"); \
  248.     (__typeof__(old)) _r_; \
  249. })
  250.  
  251. static __inline__ int
  252. ia64_atomic_add (int i, atomic_t *v)
  253. {
  254.     int old, new;
  255.     // CMPXCHG_BUGCHECK_DECL
  256.  
  257.     do {
  258.         // CMPXCHG_BUGCHECK(v);
  259.         old = atomic_read(v);
  260.         new = old + i;
  261.     } while (ia64_cmpxchg("acq", v, old, old + i, sizeof(atomic_t)) != old);
  262.     return new;
  263. }
  264.  
  265. static __inline__ int
  266. ia64_atomic_sub (int i, atomic_t *v)
  267. {
  268.     int old, new;
  269.     // CMPXCHG_BUGCHECK_DECL
  270.  
  271.     do {
  272.         // CMPXCHG_BUGCHECK(v);
  273.         old = atomic_read(v);
  274.         new = old - i;
  275.     } while (ia64_cmpxchg("acq", v, old, new, sizeof(atomic_t)) != old);
  276.     return new;
  277. }
  278.  
  279. #define IA64_FETCHADD(tmp,v,n,sz)                        \
  280. ({                                        \
  281.     switch (sz) {                                \
  282.           case 4:                                \
  283.         __asm__ __volatile__ ("fetchadd4.rel %0=[%1],%2"        \
  284.                       : "=r"(tmp) : "r"(v), "i"(n) : "memory");    \
  285.         break;                                \
  286.                                         \
  287.           case 8:                                \
  288.         __asm__ __volatile__ ("fetchadd8.rel %0=[%1],%2"        \
  289.                       : "=r"(tmp) : "r"(v), "i"(n) : "memory");    \
  290.         break;                                \
  291.     }                                    \
  292. })
  293.  
  294. #define ia64_fetch_and_add(i,v)                            \
  295. ({                                        \
  296.     unsigned long _tmp;                                \
  297.     volatile __typeof__(*(v)) *_v = (v);                    \
  298.     switch (i) {                                \
  299.           case -16:    IA64_FETCHADD(_tmp, _v, -16, sizeof(*(v))); break;    \
  300.           case  -8:    IA64_FETCHADD(_tmp, _v,  -8, sizeof(*(v))); break;    \
  301.           case  -4:    IA64_FETCHADD(_tmp, _v,  -4, sizeof(*(v))); break;    \
  302.           case  -1:    IA64_FETCHADD(_tmp, _v,  -1, sizeof(*(v))); break;    \
  303.           case   1:    IA64_FETCHADD(_tmp, _v,   1, sizeof(*(v))); break;    \
  304.           case   4:    IA64_FETCHADD(_tmp, _v,   4, sizeof(*(v))); break;    \
  305.           case   8:    IA64_FETCHADD(_tmp, _v,   8, sizeof(*(v))); break;    \
  306.           case  16:    IA64_FETCHADD(_tmp, _v,  16, sizeof(*(v))); break;    \
  307.     }                                    \
  308.     (__typeof__(*v)) (_tmp + (i));    /* return new value */            \
  309. })
  310.  
  311. /*
  312.  * Atomically add I to V and return TRUE if the resulting value is
  313.  * negative.
  314.  */
  315. static __inline__ int
  316. atomic_add_negative (int i, atomic_t *v)
  317. {
  318.     return ia64_atomic_add(i, v) < 0;
  319. }
  320.  
  321. #define atomic_add_return(i,v)                        \
  322.     ((__builtin_constant_p(i) &&                    \
  323.       (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)        \
  324.        || (i == -1) || (i == -4) || (i == -8) || (i == -16)))    \
  325.      ? ia64_fetch_and_add(i, &(v)->counter)                \
  326.      : ia64_atomic_add(i, v))
  327.  
  328. #define atomic_sub_return(i,v)                        \
  329.     ((__builtin_constant_p(i) &&                    \
  330.       (   (i ==  1) || (i ==  4) || (i ==  8) || (i ==  16)        \
  331.        || (i == -1) || (i == -4) || (i == -8) || (i == -16)))    \
  332.      ? ia64_fetch_and_add(-(i), &(v)->counter)            \
  333.      : ia64_atomic_sub(i, v))
  334.  
  335. #define atomic_dec_return(v)        atomic_sub_return(1, (v))
  336. #define atomic_inc_return(v)        atomic_add_return(1, (v))
  337.  
  338. #define atomic_sub_and_test(i,v)    (atomic_sub_return((i), (v)) == 0)
  339. #define atomic_dec_and_test(v)        (atomic_sub_return(1, (v)) == 0)
  340. #define atomic_inc_and_test(v)        (atomic_add_return(1, (v)) != 0)
  341.  
  342. #define atomic_add(i,v)            atomic_add_return((i), (v))
  343. #define atomic_sub(i,v)            atomic_sub_return((i), (v))
  344. #define atomic_inc(v)            atomic_add(1, (v))
  345. #define atomic_dec(v)            atomic_sub(1, (v))
  346.  
  347. /*
  348.  * Macros to force memory ordering.  In these descriptions, "previous"
  349.  * and "subsequent" refer to program order; "visible" means that all
  350.  * architecturally visible effects of a memory access have occurred
  351.  * (at a minimum, this means the memory has been read or written).
  352.  *
  353.  *   wmb():    Guarantees that all preceding stores to memory-
  354.  *        like regions are visible before any subsequent
  355.  *        stores and that all following stores will be
  356.  *        visible only after all previous stores.
  357.  *   rmb():    Like wmb(), but for reads.
  358.  *   mb():    wmb()/rmb() combo, i.e., all previous memory
  359.  *        accesses are visible before all subsequent
  360.  *        accesses and vice versa.  This is also known as
  361.  *        a "fence."
  362.  *
  363.  * Note: "mb()" and its variants cannot be used as a fence to order
  364.  * accesses to memory mapped I/O registers.  For that, mf.a needs to
  365.  * be used.  However, we don't want to always use mf.a because (a)
  366.  * it's (presumably) much slower than mf and (b) mf.a is supported for
  367.  * sequential memory pages only.
  368.  */
  369. #define mb()    __asm__ __volatile__ ("mf" ::: "memory")
  370. #define rmb()    mb()
  371. #define wmb()    mb()
  372.  
  373. #define IATOMIC_DEFINED        1
  374.  
  375. #endif /* __ia64__ */
  376.  
  377. #ifdef __alpha__
  378.  
  379. /*
  380.  * Atomic operations that C can't guarantee us.  Useful for
  381.  * resource counting etc...
  382.  *
  383.  * But use these as seldom as possible since they are much slower
  384.  * than regular operations.
  385.  */
  386.  
  387.  
  388. /*
  389.  * Counter is volatile to make sure gcc doesn't try to be clever
  390.  * and move things around on us. We need to use _exactly_ the address
  391.  * the user gave us, not some alias that contains the same information.
  392.  */
  393. typedef struct { volatile int counter; } atomic_t;
  394.  
  395. #define ATOMIC_INIT(i)    ( (atomic_t) { (i) } )
  396.  
  397. #define atomic_read(v)        ((v)->counter)
  398. #define atomic_set(v,i)        ((v)->counter = (i))
  399.  
  400. /*
  401.  * To get proper branch prediction for the main line, we must branch
  402.  * forward to code at the end of this object's .text section, then
  403.  * branch back to restart the operation.
  404.  */
  405.  
  406. static __inline__ void atomic_add(int i, atomic_t * v)
  407. {
  408.     unsigned long temp;
  409.     __asm__ __volatile__(
  410.     "1:    ldl_l %0,%1\n"
  411.     "    addl %0,%2,%0\n"
  412.     "    stl_c %0,%1\n"
  413.     "    beq %0,2f\n"
  414.     ".subsection 2\n"
  415.     "2:    br 1b\n"
  416.     ".previous"
  417.     :"=&r" (temp), "=m" (v->counter)
  418.     :"Ir" (i), "m" (v->counter));
  419. }
  420.  
  421. static __inline__ void atomic_sub(int i, atomic_t * v)
  422. {
  423.     unsigned long temp;
  424.     __asm__ __volatile__(
  425.     "1:    ldl_l %0,%1\n"
  426.     "    subl %0,%2,%0\n"
  427.     "    stl_c %0,%1\n"
  428.     "    beq %0,2f\n"
  429.     ".subsection 2\n"
  430.     "2:    br 1b\n"
  431.     ".previous"
  432.     :"=&r" (temp), "=m" (v->counter)
  433.     :"Ir" (i), "m" (v->counter));
  434. }
  435.  
  436. /*
  437.  * Same as above, but return the result value
  438.  */
  439. static __inline__ long atomic_add_return(int i, atomic_t * v)
  440. {
  441.     long temp, result;
  442.     __asm__ __volatile__(
  443.     "1:    ldl_l %0,%1\n"
  444.     "    addl %0,%3,%2\n"
  445.     "    addl %0,%3,%0\n"
  446.     "    stl_c %0,%1\n"
  447.     "    beq %0,2f\n"
  448.     "    mb\n"
  449.     ".subsection 2\n"
  450.     "2:    br 1b\n"
  451.     ".previous"
  452.     :"=&r" (temp), "=m" (v->counter), "=&r" (result)
  453.     :"Ir" (i), "m" (v->counter) : "memory");
  454.     return result;
  455. }
  456.  
  457. static __inline__ long atomic_sub_return(int i, atomic_t * v)
  458. {
  459.     long temp, result;
  460.     __asm__ __volatile__(
  461.     "1:    ldl_l %0,%1\n"
  462.     "    subl %0,%3,%2\n"
  463.     "    subl %0,%3,%0\n"
  464.     "    stl_c %0,%1\n"
  465.     "    beq %0,2f\n"
  466.     "    mb\n"
  467.     ".subsection 2\n"
  468.     "2:    br 1b\n"
  469.     ".previous"
  470.     :"=&r" (temp), "=m" (v->counter), "=&r" (result)
  471.     :"Ir" (i), "m" (v->counter) : "memory");
  472.     return result;
  473. }
  474.  
  475. #define atomic_dec_return(v) atomic_sub_return(1,(v))
  476. #define atomic_inc_return(v) atomic_add_return(1,(v))
  477.  
  478. #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
  479. #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
  480.  
  481. #define atomic_inc(v) atomic_add(1,(v))
  482. #define atomic_dec(v) atomic_sub(1,(v))
  483.  
  484. #define mb() \
  485. __asm__ __volatile__("mb": : :"memory")
  486.  
  487. #define rmb() \
  488. __asm__ __volatile__("mb": : :"memory")
  489.  
  490. #define wmb() \
  491. __asm__ __volatile__("wmb": : :"memory")
  492.  
  493. #define IATOMIC_DEFINED        1
  494.  
  495. #endif /* __alpha__ */
  496.  
  497. #ifdef __powerpc__
  498.  
  499. typedef struct { volatile int counter; } atomic_t;
  500.  
  501. #define ATOMIC_INIT(i)    { (i) }
  502.  
  503. #define atomic_read(v)        ((v)->counter)
  504. #define atomic_set(v,i)        (((v)->counter) = (i))
  505.  
  506. extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
  507. extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
  508.  
  509. #define SMP_ISYNC    "\n\tisync"
  510.  
  511. static __inline__ void atomic_add(int a, atomic_t *v)
  512. {
  513.     int t;
  514.  
  515.     __asm__ __volatile__(
  516. "1:    lwarx    %0,0,%3        # atomic_add\n\
  517.     add    %0,%2,%0\n\
  518.     stwcx.    %0,0,%3\n\
  519.     bne-    1b"
  520.     : "=&r" (t), "=m" (v->counter)
  521.     : "r" (a), "r" (&v->counter), "m" (v->counter)
  522.     : "cc");
  523. }
  524.  
  525. static __inline__ int atomic_add_return(int a, atomic_t *v)
  526. {
  527.     int t;
  528.  
  529.     __asm__ __volatile__(
  530. "1:    lwarx    %0,0,%2        # atomic_add_return\n\
  531.     add    %0,%1,%0\n\
  532.     stwcx.    %0,0,%2\n\
  533.     bne-    1b"
  534.     SMP_ISYNC
  535.     : "=&r" (t)
  536.     : "r" (a), "r" (&v->counter)
  537.     : "cc", "memory");
  538.  
  539.     return t;
  540. }
  541.  
  542. static __inline__ void atomic_sub(int a, atomic_t *v)
  543. {
  544.     int t;
  545.  
  546.     __asm__ __volatile__(
  547. "1:    lwarx    %0,0,%3        # atomic_sub\n\
  548.     subf    %0,%2,%0\n\
  549.     stwcx.    %0,0,%3\n\
  550.     bne-    1b"
  551.     : "=&r" (t), "=m" (v->counter)
  552.     : "r" (a), "r" (&v->counter), "m" (v->counter)
  553.     : "cc");
  554. }
  555.  
  556. static __inline__ int atomic_sub_return(int a, atomic_t *v)
  557. {
  558.     int t;
  559.  
  560.     __asm__ __volatile__(
  561. "1:    lwarx    %0,0,%2        # atomic_sub_return\n\
  562.     subf    %0,%1,%0\n\
  563.     stwcx.    %0,0,%2\n\
  564.     bne-    1b"
  565.     SMP_ISYNC
  566.     : "=&r" (t)
  567.     : "r" (a), "r" (&v->counter)
  568.     : "cc", "memory");
  569.  
  570.     return t;
  571. }
  572.  
  573. static __inline__ void atomic_inc(atomic_t *v)
  574. {
  575.     int t;
  576.  
  577.     __asm__ __volatile__(
  578. "1:    lwarx    %0,0,%2        # atomic_inc\n\
  579.     addic    %0,%0,1\n\
  580.     stwcx.    %0,0,%2\n\
  581.     bne-    1b"
  582.     : "=&r" (t), "=m" (v->counter)
  583.     : "r" (&v->counter), "m" (v->counter)
  584.     : "cc");
  585. }
  586.  
  587. static __inline__ int atomic_inc_return(atomic_t *v)
  588. {
  589.     int t;
  590.  
  591.     __asm__ __volatile__(
  592. "1:    lwarx    %0,0,%1        # atomic_inc_return\n\
  593.     addic    %0,%0,1\n\
  594.     stwcx.    %0,0,%1\n\
  595.     bne-    1b"
  596.     SMP_ISYNC
  597.     : "=&r" (t)
  598.     : "r" (&v->counter)
  599.     : "cc", "memory");
  600.  
  601.     return t;
  602. }
  603.  
  604. static __inline__ void atomic_dec(atomic_t *v)
  605. {
  606.     int t;
  607.  
  608.     __asm__ __volatile__(
  609. "1:    lwarx    %0,0,%2        # atomic_dec\n\
  610.     addic    %0,%0,-1\n\
  611.     stwcx.    %0,0,%2\n\
  612.     bne-    1b"
  613.     : "=&r" (t), "=m" (v->counter)
  614.     : "r" (&v->counter), "m" (v->counter)
  615.     : "cc");
  616. }
  617.  
  618. static __inline__ int atomic_dec_return(atomic_t *v)
  619. {
  620.     int t;
  621.  
  622.     __asm__ __volatile__(
  623. "1:    lwarx    %0,0,%1        # atomic_dec_return\n\
  624.     addic    %0,%0,-1\n\
  625.     stwcx.    %0,0,%1\n\
  626.     bne-    1b"
  627.     SMP_ISYNC
  628.     : "=&r" (t)
  629.     : "r" (&v->counter)
  630.     : "cc", "memory");
  631.  
  632.     return t;
  633. }
  634.  
  635. #define atomic_sub_and_test(a, v)    (atomic_sub_return((a), (v)) == 0)
  636. #define atomic_dec_and_test(v)        (atomic_dec_return((v)) == 0)
  637.  
  638. /*
  639.  * Atomically test *v and decrement if it is greater than 0.
  640.  * The function returns the old value of *v minus 1.
  641.  */
  642. static __inline__ int atomic_dec_if_positive(atomic_t *v)
  643. {
  644.     int t;
  645.  
  646.     __asm__ __volatile__(
  647. "1:    lwarx    %0,0,%1        # atomic_dec_if_positive\n\
  648.     addic.    %0,%0,-1\n\
  649.     blt-    2f\n\
  650.     stwcx.    %0,0,%1\n\
  651.     bne-    1b"
  652.     SMP_ISYNC
  653.     "\n\
  654. 2:"    : "=&r" (t)
  655.     : "r" (&v->counter)
  656.     : "cc", "memory");
  657.  
  658.     return t;
  659. }
  660.  
  661. /*
  662.  * Memory barrier.
  663.  * The sync instruction guarantees that all memory accesses initiated
  664.  * by this processor have been performed (with respect to all other
  665.  * mechanisms that access memory).  The eieio instruction is a barrier
  666.  * providing an ordering (separately) for (a) cacheable stores and (b)
  667.  * loads and stores to non-cacheable memory (e.g. I/O devices).
  668.  *
  669.  * mb() prevents loads and stores being reordered across this point.
  670.  * rmb() prevents loads being reordered across this point.
  671.  * wmb() prevents stores being reordered across this point.
  672.  *
  673.  * We can use the eieio instruction for wmb, but since it doesn't
  674.  * give any ordering guarantees about loads, we have to use the
  675.  * stronger but slower sync instruction for mb and rmb.
  676.  */
  677. #define mb()  __asm__ __volatile__ ("sync" : : : "memory")
  678. #define rmb()  __asm__ __volatile__ ("sync" : : : "memory")
  679. #define wmb()  __asm__ __volatile__ ("eieio" : : : "memory")
  680.  
  681. #define IATOMIC_DEFINED        1
  682.  
  683. #endif /* __powerpc__ */
  684.  
  685. #ifdef __mips__
  686.  
  687. typedef struct { volatile int counter; } atomic_t;
  688.  
  689. #define ATOMIC_INIT(i)    { (i) }
  690.  
  691. /*
  692.  * atomic_read - read atomic variable
  693.  * @v: pointer of type atomic_t
  694.  *
  695.  * Atomically reads the value of @v.  Note that the guaranteed
  696.  * useful range of an atomic_t is only 24 bits.
  697.  */
  698. #define atomic_read(v)    ((v)->counter)
  699.  
  700. /*
  701.  * atomic_set - set atomic variable
  702.  * @v: pointer of type atomic_t
  703.  * @i: required value
  704.  *
  705.  * Atomically sets the value of @v to @i.  Note that the guaranteed
  706.  * useful range of an atomic_t is only 24 bits.
  707.  */
  708. #define atomic_set(v,i)    ((v)->counter = (i))
  709.  
  710. /*
  711.  * for MIPS II and better we can use ll/sc instruction, and kernel 2.4.3+
  712.  * will emulate it on MIPS I.
  713.  */
  714.  
  715. /*
  716.  * atomic_add - add integer to atomic variable
  717.  * @i: integer value to add
  718.  * @v: pointer of type atomic_t
  719.  *
  720.  * Atomically adds @i to @v.  Note that the guaranteed useful range
  721.  * of an atomic_t is only 24 bits.
  722.  */
  723. extern __inline__ void atomic_add(int i, atomic_t * v)
  724. {
  725.     unsigned long temp;
  726.  
  727.     __asm__ __volatile__(
  728.         ".set push                            \n"
  729.         ".set mips2                           \n"
  730.         "1:   ll      %0, %1      # atomic_add\n"
  731.         "     addu    %0, %2                  \n"
  732.         "     sc      %0, %1                  \n"
  733.         "     beqz    %0, 1b                  \n"
  734.         ".set pop                             \n"
  735.         : "=&r" (temp), "=m" (v->counter)
  736.         : "Ir" (i), "m" (v->counter));
  737. }
  738.  
  739. /*
  740.  * atomic_sub - subtract the atomic variable
  741.  * @i: integer value to subtract
  742.  * @v: pointer of type atomic_t
  743.  *
  744.  * Atomically subtracts @i from @v.  Note that the guaranteed
  745.  * useful range of an atomic_t is only 24 bits.
  746.  */
  747. extern __inline__ void atomic_sub(int i, atomic_t * v)
  748. {
  749.     unsigned long temp;
  750.  
  751.     __asm__ __volatile__(
  752.         ".set push                            \n"
  753.         ".set mips2                           \n"
  754.         "1:   ll      %0, %1      # atomic_sub\n"
  755.         "     subu    %0, %2                  \n"
  756.         "     sc      %0, %1                  \n"
  757.         "     beqz    %0, 1b                  \n"
  758.         ".set pop                             \n"
  759.         : "=&r" (temp), "=m" (v->counter)
  760.         : "Ir" (i), "m" (v->counter));
  761. }
  762.  
  763. /*
  764.  * Same as above, but return the result value
  765.  */
  766. extern __inline__ int atomic_add_return(int i, atomic_t * v)
  767. {
  768.     unsigned long temp, result;
  769.  
  770.     __asm__ __volatile__(
  771.         ".set push               # atomic_add_return\n"
  772.         ".set noreorder                             \n"
  773.         ".set mips2                                 \n"
  774.         "1:   ll      %1, %2                        \n"
  775.         "     addu    %0, %1, %3                    \n"
  776.         "     sc      %0, %2                        \n"
  777.         "     beqz    %0, 1b                        \n"
  778.         "     addu    %0, %1, %3                    \n"
  779.         ".set pop                                   \n"
  780.         : "=&r" (result), "=&r" (temp), "=m" (v->counter)
  781.         : "Ir" (i), "m" (v->counter)
  782.         : "memory");
  783.  
  784.     return result;
  785. }
  786.  
  787. extern __inline__ int atomic_sub_return(int i, atomic_t * v)
  788. {
  789.     unsigned long temp, result;
  790.  
  791.     __asm__ __volatile__(
  792.         ".set push                                   \n"
  793.         ".set mips2                                  \n"
  794.         ".set noreorder           # atomic_sub_return\n"
  795.         "1:   ll    %1, %2                           \n"
  796.         "     subu  %0, %1, %3                       \n"
  797.         "     sc    %0, %2                           \n"
  798.         "     beqz  %0, 1b                           \n"
  799.         "     subu  %0, %1, %3                       \n"
  800.         ".set pop                                    \n"
  801.         : "=&r" (result), "=&r" (temp), "=m" (v->counter)
  802.         : "Ir" (i), "m" (v->counter)
  803.         : "memory");
  804.  
  805.     return result;
  806. }
  807.  
  808. #define atomic_dec_return(v) atomic_sub_return(1,(v))
  809. #define atomic_inc_return(v) atomic_add_return(1,(v))
  810.  
  811. /*
  812.  * atomic_sub_and_test - subtract value from variable and test result
  813.  * @i: integer value to subtract
  814.  * @v: pointer of type atomic_t
  815.  *
  816.  * Atomically subtracts @i from @v and returns
  817.  * true if the result is zero, or false for all
  818.  * other cases.  Note that the guaranteed
  819.  * useful range of an atomic_t is only 24 bits.
  820.  */
  821. #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
  822.  
  823. /*
  824.  * atomic_inc_and_test - increment and test
  825.  * @v: pointer of type atomic_t
  826.  *
  827.  * Atomically increments @v by 1
  828.  * and returns true if the result is zero, or false for all
  829.  * other cases.  Note that the guaranteed
  830.  * useful range of an atomic_t is only 24 bits.
  831.  */
  832. #define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0)
  833.  
  834. /*
  835.  * atomic_dec_and_test - decrement by 1 and test
  836.  * @v: pointer of type atomic_t
  837.  *
  838.  * Atomically decrements @v by 1 and
  839.  * returns true if the result is 0, or false for all other
  840.  * cases.  Note that the guaranteed
  841.  * useful range of an atomic_t is only 24 bits.
  842.  */
  843. #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
  844.  
  845. /*
  846.  * atomic_inc - increment atomic variable
  847.  * @v: pointer of type atomic_t
  848.  *
  849.  * Atomically increments @v by 1.  Note that the guaranteed
  850.  * useful range of an atomic_t is only 24 bits.
  851.  */
  852. #define atomic_inc(v) atomic_add(1,(v))
  853.  
  854. /*
  855.  * atomic_dec - decrement and test
  856.  * @v: pointer of type atomic_t
  857.  *
  858.  * Atomically decrements @v by 1.  Note that the guaranteed
  859.  * useful range of an atomic_t is only 24 bits.
  860.  */
  861. #define atomic_dec(v) atomic_sub(1,(v))
  862.  
  863. /*
  864.  * atomic_add_negative - add and test if negative
  865.  * @v: pointer of type atomic_t
  866.  * @i: integer value to add
  867.  *
  868.  * Atomically adds @i to @v and returns true
  869.  * if the result is negative, or false when
  870.  * result is greater than or equal to zero.  Note that the guaranteed
  871.  * useful range of an atomic_t is only 24 bits.
  872.  *
  873.  * Currently not implemented for MIPS.
  874.  */
  875.  
  876. #define mb()                        \
  877. __asm__ __volatile__(                    \
  878.     "# prevent instructions being moved around\n\t"    \
  879.     ".set\tnoreorder\n\t"                \
  880.     "# 8 nops to fool the R4400 pipeline\n\t"    \
  881.     "nop;nop;nop;nop;nop;nop;nop;nop\n\t"        \
  882.     ".set\treorder"                    \
  883.     : /* no output */                \
  884.     : /* no input */                \
  885.     : "memory")
  886. #define rmb() mb()
  887. #define wmb() mb()
  888.  
  889. #define IATOMIC_DEFINED        1
  890.  
  891. #endif /* __mips__ */
  892.  
  893. #ifdef __arm__
  894.  
  895. /*
  896.  * FIXME: bellow code is valid only for SA11xx
  897.  */
  898.  
  899. /*
  900.  * Save the current interrupt enable state & disable IRQs
  901.  */
  902. #define local_irq_save(x)                    \
  903.     ({                            \
  904.         unsigned long temp;                \
  905.     __asm__ __volatile__(                    \
  906.     "mrs    %0, cpsr        @ local_irq_save\n"    \
  907. "    orr    %1, %0, #128\n"                    \
  908. "    msr    cpsr_c, %1"                    \
  909.     : "=r" (x), "=r" (temp)                    \
  910.     :                            \
  911.     : "memory");                        \
  912.     })
  913.  
  914. /*
  915.  * restore saved IRQ & FIQ state
  916.  */
  917. #define local_irq_restore(x)                    \
  918.     __asm__ __volatile__(                    \
  919.     "msr    cpsr_c, %0        @ local_irq_restore\n"    \
  920.     :                            \
  921.     : "r" (x)                        \
  922.     : "memory")
  923.  
  924. #define __save_flags_cli(x) local_irq_save(x)
  925. #define __restore_flags(x) local_irq_restore(x)
  926.  
  927. typedef struct { volatile int counter; } atomic_t;
  928.  
  929. #define ATOMIC_INIT(i)    { (i) }
  930.  
  931. #define atomic_read(v)    ((v)->counter)
  932. #define atomic_set(v,i)    (((v)->counter) = (i))
  933.  
  934. static __inline__ void atomic_add(int i, volatile atomic_t *v)
  935. {
  936.     unsigned long flags;
  937.  
  938.     __save_flags_cli(flags);
  939.     v->counter += i;
  940.     __restore_flags(flags);
  941. }
  942.  
  943. static __inline__ void atomic_sub(int i, volatile atomic_t *v)
  944. {
  945.     unsigned long flags;
  946.  
  947.     __save_flags_cli(flags);
  948.     v->counter -= i;
  949.     __restore_flags(flags);
  950. }
  951.  
  952. static __inline__ void atomic_inc(volatile atomic_t *v)
  953. {
  954.     unsigned long flags;
  955.  
  956.     __save_flags_cli(flags);
  957.     v->counter += 1;
  958.     __restore_flags(flags);
  959. }
  960.  
  961. static __inline__ void atomic_dec(volatile atomic_t *v)
  962. {
  963.     unsigned long flags;
  964.  
  965.     __save_flags_cli(flags);
  966.     v->counter -= 1;
  967.     __restore_flags(flags);
  968. }
  969.  
  970. static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
  971. {
  972.     unsigned long flags;
  973.     int result;
  974.  
  975.     __save_flags_cli(flags);
  976.     v->counter -= 1;
  977.     result = (v->counter == 0);
  978.     __restore_flags(flags);
  979.  
  980.     return result;
  981. }
  982.  
  983. static inline int atomic_add_negative(int i, volatile atomic_t *v)
  984. {
  985.     unsigned long flags;
  986.     int result;
  987.  
  988.     __save_flags_cli(flags);
  989.     v->counter += i;
  990.     result = (v->counter < 0);
  991.     __restore_flags(flags);
  992.  
  993.     return result;
  994. }
  995.  
  996. static __inline__ void atomic_clear_mask(unsigned long mask, unsigned long *addr)
  997. {
  998.     unsigned long flags;
  999.  
  1000.     __save_flags_cli(flags);
  1001.     *addr &= ~mask;
  1002.     __restore_flags(flags);
  1003. }
  1004.  
  1005. #define mb() __asm__ __volatile__ ("" : : : "memory")
  1006. #define rmb() mb()
  1007. #define wmb() mb()
  1008.  
  1009. #define IATOMIC_DEFINED        1
  1010.  
  1011. #endif /* __arm__ */
  1012.  
  1013. #ifdef __sh__
  1014.  
  1015. typedef struct { volatile int counter; } atomic_t;
  1016.  
  1017. #define ATOMIC_INIT(i)    { (i) }
  1018.  
  1019. #define atomic_read(v)            ((v)->counter)
  1020. #define atomic_set(v,i)            (((v)->counter) = (i))
  1021.  
  1022. #define atomic_dec_return(v)        atomic_sub_return(1,(v))
  1023. #define atomic_inc_return(v)        atomic_add_return(1,(v))
  1024.  
  1025. #define atomic_sub_and_test(i,v)    (atomic_sub_return((i), (v)) == 0)
  1026. #define atomic_dec_and_test(v)        (atomic_sub_return(1, (v)) == 0)
  1027. #define atomic_inc_and_test(v)        (atomic_add_return(1, (v)) != 0)
  1028.  
  1029. #define atomic_add(i,v)            atomic_add_return((i),(v))
  1030. #define atomic_sub(i,v)            atomic_sub_return((i),(v))
  1031. #define atomic_inc(v)            atomic_add(1,(v))
  1032. #define atomic_dec(v)            atomic_sub(1,(v))
  1033.  
  1034. static __inline__ int atomic_add_return(int i, volatile atomic_t *v)
  1035. {
  1036.     int result;
  1037.  
  1038.     asm volatile (
  1039.     "    .align    2\n"
  1040.     "    mova    99f, r0\n"
  1041.     "    mov    r15, r1\n"
  1042.     "    mov    #-6, r15\n"
  1043.     "    mov.l    @%2, %0\n"
  1044.     "    add    %1, %0\n"
  1045.     "    mov.l    %0, @%2\n"
  1046.     "99:    mov    r1, r15"
  1047.     : "=&r"(result)
  1048.     : "r"(i), "r"(v)
  1049.     : "r0", "r1");
  1050.  
  1051.     return result;
  1052. }
  1053.  
  1054. static __inline__ int atomic_sub_return(int i, volatile atomic_t *v)
  1055. {
  1056.     int result;
  1057.  
  1058.     asm volatile (
  1059.     "    .align    2\n"
  1060.     "    mova    99f, r0\n"
  1061.     "    mov    r15, r1\n"
  1062.     "    mov    #-6, r15\n"
  1063.     "    mov.l    @%2, %0\n"
  1064.     "    sub    %1, %0\n"
  1065.     "    mov.l    %0, @%2\n"
  1066.     "99:    mov    r1, r15"
  1067.     : "=&r"(result)
  1068.     : "r"(i), "r"(v)
  1069.     : "r0", "r1");
  1070.  
  1071.     return result;
  1072. }
  1073.  
  1074. #define mb() __asm__ __volatile__ ("" : : : "memory")
  1075. #define rmb() mb()
  1076. #define wmb() mb()
  1077.  
  1078. #define IATOMIC_DEFINED        1
  1079.  
  1080. #endif /* __sh__ */
  1081.  
  1082. #ifndef IATOMIC_DEFINED
  1083. /*
  1084.  * non supported architecture.
  1085.  */
  1086. #warning "Atomic operations are not supported on this architecture."
  1087.  
  1088. typedef struct { volatile int counter; } atomic_t;
  1089.  
  1090. #define ATOMIC_INIT(i)    { (i) }
  1091.  
  1092. #define atomic_read(v)    ((v)->counter)
  1093. #define atomic_set(v,i)    (((v)->counter) = (i))
  1094. #define atomic_add(i,v) (((v)->counter) += (i))
  1095. #define atomic_sub(i,v) (((v)->counter) -= (i))
  1096. #define atomic_inc(v)   (((v)->counter)++)
  1097. #define atomic_dec(v)   (((v)->counter)--)
  1098.  
  1099. #define mb()
  1100. #define rmb()
  1101. #define wmb()
  1102.  
  1103. #define IATOMIC_DEFINED        1
  1104.  
  1105. #endif /* IATOMIC_DEFINED */
  1106.  
  1107. /*
  1108.  *  Atomic read/write
  1109.  *  Copyright (c) 2001 by Abramo Bagnara <abramo@alsa-project.org>
  1110.  */
  1111.  
  1112. /* Max number of times we must spin on a spin-lock calling sched_yield().
  1113.    After MAX_SPIN_COUNT iterations, we put the calling thread to sleep. */
  1114.  
  1115. #ifndef MAX_SPIN_COUNT
  1116. #define MAX_SPIN_COUNT 50
  1117. #endif
  1118.  
  1119. /* Duration of sleep (in nanoseconds) when we can't acquire a spin-lock
  1120.    after MAX_SPIN_COUNT iterations of sched_yield().
  1121.    This MUST BE > 2ms.
  1122.    (Otherwise the kernel does busy-waiting for real-time threads,
  1123.     giving other threads no chance to run.) */
  1124.  
  1125. #ifndef SPIN_SLEEP_DURATION
  1126. #define SPIN_SLEEP_DURATION 2000001
  1127. #endif
  1128.  
  1129. typedef struct {
  1130.     unsigned int begin, end;
  1131. } snd_atomic_write_t;
  1132.  
  1133. typedef struct {
  1134.     volatile const snd_atomic_write_t *write;
  1135.     unsigned int end;
  1136. } snd_atomic_read_t;
  1137.  
  1138. void snd_atomic_read_wait(snd_atomic_read_t *t);
  1139.  
  1140. static inline void snd_atomic_write_init(snd_atomic_write_t *w)
  1141. {
  1142.     w->begin = 0;
  1143.     w->end = 0;
  1144. }
  1145.  
  1146. static inline void snd_atomic_write_begin(snd_atomic_write_t *w)
  1147. {
  1148.     w->begin++;
  1149.     wmb();
  1150. }
  1151.  
  1152. static inline void snd_atomic_write_end(snd_atomic_write_t *w)
  1153. {
  1154.     wmb();
  1155.     w->end++;
  1156. }
  1157.  
  1158. static inline void snd_atomic_read_init(snd_atomic_read_t *r, snd_atomic_write_t *w)
  1159. {
  1160.     r->write = w;
  1161. }
  1162.  
  1163. static inline void snd_atomic_read_begin(snd_atomic_read_t *r)
  1164. {
  1165.     r->end = r->write->end;
  1166.     rmb();
  1167. }
  1168.  
  1169. static inline int snd_atomic_read_ok(snd_atomic_read_t *r)
  1170. {
  1171.     rmb();
  1172.     return r->end == r->write->begin;
  1173. }
  1174.  
  1175. #endif /* __ALSA_IATOMIC_H */
  1176.