Home | History | Annotate | Download | only in include
      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 (at) 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