1 /*
2     Copyright (C) 2001 Paul Davis and others (see below)
3     Code derived from various headers from the Linux kernel.
4        Copyright attributions maintained where present.
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 
20     $Id: atomic.h,v 1.8 2009-03-29 18:43:39 schoenebeck Exp $
21 */
22 
23 /*
24   CAUTION: don't ever include this file in header files that are exposed
25   to the liblinuxsampler C++ API !!! This file will not be installed along
26   with liblinuxsampler's header files! This is due to the fact that
27   atomic.h is architecture specific and would in turn require us to include
28   and export config.h, which is definitely a bad idea.
29 */
30 
31 #ifndef __linuxsampler_atomic_h__
32 #define __linuxsampler_atomic_h__
33 
34 // needed to automatically include config.h
35 #include "global.h"
36 
37 #ifdef HAVE_SMP      /* a macro we control, to manage ... */
38 #define CONFIG_SMP   /* ... the macro the kernel headers use */
39 #endif
40 
41 #if defined(__linux__) || defined(WIN32) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__)
42 #ifdef _ARCH_PPC
43 
44 /*
45  * BK Id: SCCS/s.atomic.h 1.15 10/28/01 10:37:22 trini
46  */
47 /*
48  * PowerPC atomic operations
49  */
50 
51 #ifndef _ASM_PPC_ATOMIC_H_
52 #define _ASM_PPC_ATOMIC_H_
53 
54 typedef struct { volatile int counter; } atomic_t;
55 
56 
57 #define ATOMIC_INIT(i)	{ (i) }
58 
59 #define atomic_read(v)		((v)->counter)
60 #define atomic_set(v,i)		(((v)->counter) = (i))
61 
62 extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
63 extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
64 
65 #ifdef CONFIG_SMP
66 #define SMP_ISYNC	"\n\tisync"
67 #else
68 #define SMP_ISYNC
69 #endif
70 
atomic_add(int a,atomic_t * v)71 static __inline__ void atomic_add(int a, atomic_t *v)
72 {
73 	int t;
74 
75 	__asm__ __volatile__(
76 "1:	lwarx	%0,0,%3\n\
77 	add	%0,%2,%0\n\
78 	stwcx.	%0,0,%3\n\
79 	bne-	1b"
80 	: "=&r" (t), "=m" (v->counter)
81 	: "r" (a), "r" (&v->counter), "m" (v->counter)
82 	: "cc");
83 }
84 
atomic_add_return(int a,atomic_t * v)85 static __inline__ int atomic_add_return(int a, atomic_t *v)
86 {
87 	int t;
88 
89 	__asm__ __volatile__(
90 "1:	lwarx	%0,0,%2\n\
91 	add	%0,%1,%0\n\
92 	stwcx.	%0,0,%2\n\
93 	bne-	1b"
94 	SMP_ISYNC
95 	: "=&r" (t)
96 	: "r" (a), "r" (&v->counter)
97 	: "cc", "memory");
98 
99 	return t;
100 }
101 
atomic_sub(int a,atomic_t * v)102 static __inline__ void atomic_sub(int a, atomic_t *v)
103 {
104 	int t;
105 
106 	__asm__ __volatile__(
107 "1:	lwarx	%0,0,%3\n\
108 	subf	%0,%2,%0\n\
109 	stwcx.	%0,0,%3\n\
110 	bne-	1b"
111 	: "=&r" (t), "=m" (v->counter)
112 	: "r" (a), "r" (&v->counter), "m" (v->counter)
113 	: "cc");
114 }
115 
atomic_sub_return(int a,atomic_t * v)116 static __inline__ int atomic_sub_return(int a, atomic_t *v)
117 {
118 	int t;
119 
120 	__asm__ __volatile__(
121 "1:	lwarx	%0,0,%2\n\
122 	subf	%0,%1,%0\n\
123 	stwcx.	%0,0,%2\n\
124 	bne-	1b"
125 	SMP_ISYNC
126 	: "=&r" (t)
127 	: "r" (a), "r" (&v->counter)
128 	: "cc", "memory");
129 
130 	return t;
131 }
132 
atomic_inc(atomic_t * v)133 static __inline__ void atomic_inc(atomic_t *v)
134 {
135 	int t;
136 
137 	__asm__ __volatile__(
138 "1:	lwarx	%0,0,%2\n\
139 	addic	%0,%0,1\n\
140 	stwcx.	%0,0,%2\n\
141 	bne-	1b"
142 	: "=&r" (t), "=m" (v->counter)
143 	: "r" (&v->counter), "m" (v->counter)
144 	: "cc");
145 }
146 
atomic_inc_return(atomic_t * v)147 static __inline__ int atomic_inc_return(atomic_t *v)
148 {
149 	int t;
150 
151 	__asm__ __volatile__(
152 "1:	lwarx	%0,0,%1\n\
153 	addic	%0,%0,1\n\
154 	stwcx.	%0,0,%1\n\
155 	bne-	1b"
156 	SMP_ISYNC
157 	: "=&r" (t)
158 	: "r" (&v->counter)
159 	: "cc", "memory");
160 
161 	return t;
162 }
163 
atomic_dec(atomic_t * v)164 static __inline__ void atomic_dec(atomic_t *v)
165 {
166 	int t;
167 
168 	__asm__ __volatile__(
169 "1:	lwarx	%0,0,%2\n\
170 	addic	%0,%0,-1\n\
171 	stwcx.	%0,0,%2\n\
172 	bne-	1b"
173 	: "=&r" (t), "=m" (v->counter)
174 	: "r" (&v->counter), "m" (v->counter)
175 	: "cc");
176 }
177 
atomic_dec_return(atomic_t * v)178 static __inline__ int atomic_dec_return(atomic_t *v)
179 {
180 	int t;
181 
182 	__asm__ __volatile__(
183 "1:	lwarx	%0,0,%1\n\
184 	addic	%0,%0,-1\n\
185 	stwcx.	%0,0,%1\n\
186 	bne-	1b"
187 	SMP_ISYNC
188 	: "=&r" (t)
189 	: "r" (&v->counter)
190 	: "cc", "memory");
191 
192 	return t;
193 }
194 
195 #define atomic_sub_and_test(a, v)	(atomic_sub_return((a), (v)) == 0)
196 #define atomic_dec_and_test(v)		(atomic_dec_return((v)) == 0)
197 
198 /*
199  * Atomically test *v and decrement if it is greater than 0.
200  * The function returns the old value of *v minus 1.
201  */
atomic_dec_if_positive(atomic_t * v)202 static __inline__ int atomic_dec_if_positive(atomic_t *v)
203 {
204 	int t;
205 
206 	__asm__ __volatile__(
207 "1:	lwarx	%0,0,%1\n\
208 	addic.	%0,%0,-1\n\
209 	blt-	2f\n\
210 	stwcx.	%0,0,%1\n\
211 	bne-	1b"
212 	SMP_ISYNC
213 	"\n\
214 2:"	: "=&r" (t)
215 	: "r" (&v->counter)
216 	: "cc", "memory");
217 
218 	return t;
219 }
220 
221 #define smp_mb__before_atomic_dec()	smp_mb()
222 #define smp_mb__after_atomic_dec()	smp_mb()
223 #define smp_mb__before_atomic_inc()	smp_mb()
224 #define smp_mb__after_atomic_inc()	smp_mb()
225 
226 #endif /* _ASM_PPC_ATOMIC_H_ */
227 
228 /***********************************************************************/
229 
230 #  else  /* !PPC */
231 
232 #if defined(__i386__) || defined(__x86_64__)
233 
234 #ifndef __ARCH_I386_ATOMIC__
235 #define __ARCH_I386_ATOMIC__
236 
237 /*
238  * Atomic operations that C can't guarantee us.  Useful for
239  * resource counting etc..
240  */
241 
242 #ifdef CONFIG_SMP
243 #define SMP_LOCK "lock ; "
244 #else
245 #define SMP_LOCK ""
246 #endif
247 
248 /*
249  * Make sure gcc doesn't try to be clever and move things around
250  * on us. We need to use _exactly_ the address the user gave us,
251  * not some alias that contains the same information.
252  */
253 typedef struct { volatile int counter; } atomic_t;
254 
255 #define ATOMIC_INIT(i)	{ (i) }
256 
257 /**
258  * atomic_read - read atomic variable
259  * @v: pointer of type atomic_t
260  *
261  * Atomically reads the value of @v.  Note that the guaranteed
262  * useful range of an atomic_t is only 24 bits.
263  */
264 #define atomic_read(v)		((v)->counter)
265 
266 /**
267  * atomic_set - set atomic variable
268  * @v: pointer of type atomic_t
269  * @i: required value
270  *
271  * Atomically sets the value of @v to @i.  Note that the guaranteed
272  * useful range of an atomic_t is only 24 bits.
273  */
274 #define atomic_set(v,i)		(((v)->counter) = (i))
275 
276 /**
277  * atomic_add - add integer to atomic variable
278  * @i: integer value to add
279  * @v: pointer of type atomic_t
280  *
281  * Atomically adds @i to @v.  Note that the guaranteed useful range
282  * of an atomic_t is only 24 bits.
283  */
atomic_add(int i,atomic_t * v)284 static __inline__ void atomic_add(int i, atomic_t *v)
285 {
286 	__asm__ __volatile__(
287 		SMP_LOCK "addl %1,%0"
288 		:"=m" (v->counter)
289 		:"ir" (i), "m" (v->counter));
290 }
291 
292 /**
293  * atomic_sub - subtract the atomic variable
294  * @i: integer value to subtract
295  * @v: pointer of type atomic_t
296  *
297  * Atomically subtracts @i from @v.  Note that the guaranteed
298  * useful range of an atomic_t is only 24 bits.
299  */
atomic_sub(int i,atomic_t * v)300 static __inline__ void atomic_sub(int i, atomic_t *v)
301 {
302 	__asm__ __volatile__(
303 		SMP_LOCK "subl %1,%0"
304 		:"=m" (v->counter)
305 		:"ir" (i), "m" (v->counter));
306 }
307 
308 /**
309  * atomic_sub_and_test - subtract value from variable and test result
310  * @i: integer value to subtract
311  * @v: pointer of type atomic_t
312  *
313  * Atomically subtracts @i from @v and returns
314  * true if the result is zero, or false for all
315  * other cases.  Note that the guaranteed
316  * useful range of an atomic_t is only 24 bits.
317  */
atomic_sub_and_test(int i,atomic_t * v)318 static __inline__ int atomic_sub_and_test(int i, atomic_t *v)
319 {
320 	unsigned char c;
321 
322 	__asm__ __volatile__(
323 		SMP_LOCK "subl %2,%0; sete %1"
324 		:"=m" (v->counter), "=qm" (c)
325 		:"ir" (i), "m" (v->counter) : "memory");
326 	return c;
327 }
328 
329 /**
330  * atomic_inc - increment atomic variable
331  * @v: pointer of type atomic_t
332  *
333  * Atomically increments @v by 1.  Note that the guaranteed
334  * useful range of an atomic_t is only 24 bits.
335  */
atomic_inc(atomic_t * v)336 static __inline__ void atomic_inc(atomic_t *v)
337 {
338 	__asm__ __volatile__(
339 		SMP_LOCK "incl %0"
340 		:"=m" (v->counter)
341 		:"m" (v->counter));
342 }
343 
344 /**
345  * atomic_dec - decrement atomic variable
346  * @v: pointer of type atomic_t
347  *
348  * Atomically decrements @v by 1.  Note that the guaranteed
349  * useful range of an atomic_t is only 24 bits.
350  */
atomic_dec(atomic_t * v)351 static __inline__ void atomic_dec(atomic_t *v)
352 {
353 	__asm__ __volatile__(
354 		SMP_LOCK "decl %0"
355 		:"=m" (v->counter)
356 		:"m" (v->counter));
357 }
358 
359 /**
360  * atomic_dec_and_test - decrement and test
361  * @v: pointer of type atomic_t
362  *
363  * Atomically decrements @v by 1 and
364  * returns true if the result is 0, or false for all other
365  * cases.  Note that the guaranteed
366  * useful range of an atomic_t is only 24 bits.
367  */
atomic_dec_and_test(atomic_t * v)368 static __inline__ int atomic_dec_and_test(atomic_t *v)
369 {
370 	unsigned char c;
371 
372 	__asm__ __volatile__(
373 		SMP_LOCK "decl %0; sete %1"
374 		:"=m" (v->counter), "=qm" (c)
375 		:"m" (v->counter) : "memory");
376 	return c != 0;
377 }
378 
379 /**
380  * atomic_inc_and_test - increment and test
381  * @v: pointer of type atomic_t
382  *
383  * Atomically increments @v by 1
384  * and returns true if the result is zero, or false for all
385  * other cases.  Note that the guaranteed
386  * useful range of an atomic_t is only 24 bits.
387  */
atomic_inc_and_test(atomic_t * v)388 static __inline__ int atomic_inc_and_test(atomic_t *v)
389 {
390 	unsigned char c;
391 
392 	__asm__ __volatile__(
393 		SMP_LOCK "incl %0; sete %1"
394 		:"=m" (v->counter), "=qm" (c)
395 		:"m" (v->counter) : "memory");
396 	return c != 0;
397 }
398 
399 /**
400  * atomic_add_negative - add and test if negative
401  * @v: pointer of type atomic_t
402  * @i: integer value to add
403  *
404  * Atomically adds @i to @v and returns true
405  * if the result is negative, or false when
406  * result is greater than or equal to zero.  Note that the guaranteed
407  * useful range of an atomic_t is only 24 bits.
408  */
atomic_add_negative(int i,atomic_t * v)409 static __inline__ int atomic_add_negative(int i, atomic_t *v)
410 {
411 	unsigned char c;
412 
413 	__asm__ __volatile__(
414 		SMP_LOCK "addl %2,%0; sets %1"
415 		:"=m" (v->counter), "=qm" (c)
416 		:"ir" (i), "m" (v->counter) : "memory");
417 	return c;
418 }
419 
420 /* These are x86-specific, used by some header files */
421 #define atomic_clear_mask(mask, addr) \
422 __asm__ __volatile__(SMP_LOCK "andl %0,%1" \
423 : : "r" (~(mask)),"m" (*addr) : "memory")
424 
425 #define atomic_set_mask(mask, addr) \
426 __asm__ __volatile__(SMP_LOCK "orl %0,%1" \
427 : : "r" (mask),"m" (*addr) : "memory")
428 
429 /* Atomic operations are already serializing on x86 */
430 #define smp_mb__before_atomic_dec()	barrier()
431 #define smp_mb__after_atomic_dec()	barrier()
432 #define smp_mb__before_atomic_inc()	barrier()
433 #define smp_mb__after_atomic_inc()	barrier()
434 
435 #endif /* __ARCH_I386_ATOMIC__ */
436 
437 /***********************************************************************/
438 
439 #else /* !PPC && !i386 */
440 
441 #ifdef __sparc__
442 
443 /* atomic.h: These still suck, but the I-cache hit rate is higher.
444  *
445  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
446  * Copyright (C) 2000 Anton Blanchard (anton@linuxcare.com.au)
447  */
448 
449 #ifndef __ARCH_SPARC_ATOMIC__
450 #define __ARCH_SPARC_ATOMIC__
451 
452 typedef struct { volatile int counter; } atomic_t;
453 
454 #ifndef CONFIG_SMP
455 
456 #define ATOMIC_INIT(i)  { (i) }
457 #define atomic_read(v)          ((v)->counter)
458 #define atomic_set(v, i)        (((v)->counter) = i)
459 
460 #else
461 /* We do the bulk of the actual work out of line in two common
462  * routines in assembler, see arch/sparc/lib/atomic.S for the
463  * "fun" details.
464  *
465  * For SMP the trick is you embed the spin lock byte within
466  * the word, use the low byte so signedness is easily retained
467  * via a quick arithmetic shift.  It looks like this:
468  *
469  *	----------------------------------------
470  *	| signed 24-bit counter value |  lock  |  atomic_t
471  *	----------------------------------------
472  *	 31                          8 7      0
473  */
474 
475 #define ATOMIC_INIT(i)	{ (i << 8) }
476 
atomic_read(atomic_t * v)477 static __inline__ int atomic_read(atomic_t *v)
478 {
479 	int ret = v->counter;
480 
481 	while(ret & 0xff)
482 		ret = v->counter;
483 
484 	return ret >> 8;
485 }
486 
487 #define atomic_set(v, i)	(((v)->counter) = ((i) << 8))
488 #endif
489 
__atomic_add(int i,atomic_t * v)490 static __inline__ int __atomic_add(int i, atomic_t *v)
491 {
492 	register volatile int *ptr asm("g1");
493 	register int increment asm("g2");
494 
495 	ptr = &v->counter;
496 	increment = i;
497 
498 	__asm__ __volatile__(
499 	"mov	%%o7, %%g4\n\t"
500 	"call	___atomic_add\n\t"
501 	" add	%%o7, 8, %%o7\n"
502 	: "=&r" (increment)
503 	: "0" (increment), "r" (ptr)
504 	: "g3", "g4", "g7", "memory", "cc");
505 
506 	return increment;
507 }
508 
__atomic_sub(int i,atomic_t * v)509 static __inline__ int __atomic_sub(int i, atomic_t *v)
510 {
511 	register volatile int *ptr asm("g1");
512 	register int increment asm("g2");
513 
514 	ptr = &v->counter;
515 	increment = i;
516 
517 	__asm__ __volatile__(
518 	"mov	%%o7, %%g4\n\t"
519 	"call	___atomic_sub\n\t"
520 	" add	%%o7, 8, %%o7\n"
521 	: "=&r" (increment)
522 	: "0" (increment), "r" (ptr)
523 	: "g3", "g4", "g7", "memory", "cc");
524 
525 	return increment;
526 }
527 
528 #define atomic_add(i, v) ((void)__atomic_add((i), (v)))
529 #define atomic_sub(i, v) ((void)__atomic_sub((i), (v)))
530 
531 #define atomic_dec_return(v) __atomic_sub(1, (v))
532 #define atomic_inc_return(v) __atomic_add(1, (v))
533 
534 #define atomic_sub_and_test(i, v) (__atomic_sub((i), (v)) == 0)
535 #define atomic_dec_and_test(v) (__atomic_sub(1, (v)) == 0)
536 
537 #define atomic_inc(v) ((void)__atomic_add(1, (v)))
538 #define atomic_dec(v) ((void)__atomic_sub(1, (v)))
539 
540 #define atomic_add_negative(i, v) (__atomic_add((i), (v)) < 0)
541 
542 /* Atomic operations are already serializing */
543 #define smp_mb__before_atomic_dec()	barrier()
544 #define smp_mb__after_atomic_dec()	barrier()
545 #define smp_mb__before_atomic_inc()	barrier()
546 #define smp_mb__after_atomic_inc()	barrier()
547 
548 
549 #endif /* !(__ARCH_SPARC_ATOMIC__) */
550 
551 /***********************************************************************/
552 
553 #else
554 
555 #ifdef __ia64__
556 
557 #ifndef __ARCH_IA64_ATOMIC__
558 #define __ARCH_IA64_ATOMIC__
559 
560 typedef volatile int atomic_t;
561 
562 inline
563 int
atomic_read(const atomic_t * a)564 atomic_read (const atomic_t * a)
565 {
566 	return *a;
567 }
568 
569 inline
570 void
atomic_set(atomic_t * a,int v)571 atomic_set(atomic_t *a, int v)
572 {
573 	*a = v;
574 }
575 
576 inline
577 void
atomic_inc(atomic_t * v)578 atomic_inc (atomic_t *v)
579 {
580 	int old, r;
581 
582 	do {
583 		old = atomic_read(v);
584 		__asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old));
585 		__asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv"
586 				      : "=r"(r) : "r"(v), "r"(old + 1)
587 				      : "memory");
588 	} while (r != old);
589 }
590 
591 inline
592 void
atomic_dec(atomic_t * v)593 atomic_dec (atomic_t *v)
594 {
595 	int old, r;
596 
597 	do {
598 		old = atomic_read(v);
599 		__asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old));
600 		__asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv"
601 				      : "=r"(r) : "r"(v), "r"(old - 1)
602 				      : "memory");
603 	} while (r != old);
604 }
605 
606 inline
607 int
atomic_dec_and_test(atomic_t * v)608 atomic_dec_and_test (atomic_t *v)
609 {
610 	int old, r;
611 
612 	do {
613 		old = atomic_read(v);
614 		__asm__ __volatile__ ("mov ar.ccv=%0;;" :: "rO" (old));
615 		__asm__ __volatile__ ("cmpxchg4.acq %0=[%1],%2,ar.ccv"
616 				      : "=r"(r) : "r"(v), "r"(old - 1)
617 				      : "memory");
618 	} while (r != old);
619 	return old != 1;
620 }
621 
622 #endif /* !(__ARCH_IA64_ATOMIC__) */
623 
624 #else
625 
626 #ifdef __alpha__
627 
628 #ifndef _ALPHA_ATOMIC_H
629 #define _ALPHA_ATOMIC_H
630 
631 /*
632  * Atomic operations that C can't guarantee us.  Useful for
633  * resource counting etc...
634  *
635  * But use these as seldom as possible since they are much slower
636  * than regular operations.
637  */
638 
639 
640 /*
641  * Counter is volatile to make sure gcc doesn't try to be clever
642  * and move things around on us. We need to use _exactly_ the address
643  * the user gave us, not some alias that contains the same information.
644  */
645 typedef struct { volatile int counter; } atomic_t;
646 
647 #define ATOMIC_INIT(i)	( (atomic_t) { (i) } )
648 
649 #define atomic_read(v)		((v)->counter)
650 #define atomic_set(v,i)		((v)->counter = (i))
651 
652 /*
653  * To get proper branch prediction for the main line, we must branch
654  * forward to code at the end of this object's .text section, then
655  * branch back to restart the operation.
656  */
657 
atomic_add(int i,atomic_t * v)658 static __inline__ void atomic_add(int i, atomic_t * v)
659 {
660 	unsigned long temp;
661 	__asm__ __volatile__(
662 	"1:	ldl_l %0,%1\n"
663 	"	addl %0,%2,%0\n"
664 	"	stl_c %0,%1\n"
665 	"	beq %0,2f\n"
666 	".subsection 2\n"
667 	"2:	br 1b\n"
668 	".previous"
669 	:"=&r" (temp), "=m" (v->counter)
670 	:"Ir" (i), "m" (v->counter));
671 }
672 
atomic_sub(int i,atomic_t * v)673 static __inline__ void atomic_sub(int i, atomic_t * v)
674 {
675 	unsigned long temp;
676 	__asm__ __volatile__(
677 	"1:	ldl_l %0,%1\n"
678 	"	subl %0,%2,%0\n"
679 	"	stl_c %0,%1\n"
680 	"	beq %0,2f\n"
681 	".subsection 2\n"
682 	"2:	br 1b\n"
683 	".previous"
684 	:"=&r" (temp), "=m" (v->counter)
685 	:"Ir" (i), "m" (v->counter));
686 }
687 
688 /*
689  * Same as above, but return the result value
690  */
atomic_add_return(int i,atomic_t * v)691 static __inline__ long atomic_add_return(int i, atomic_t * v)
692 {
693 	long temp, result;
694 	__asm__ __volatile__(
695 	"1:	ldl_l %0,%1\n"
696 	"	addl %0,%3,%2\n"
697 	"	addl %0,%3,%0\n"
698 	"	stl_c %0,%1\n"
699 	"	beq %0,2f\n"
700 	"	mb\n"
701 	".subsection 2\n"
702 	"2:	br 1b\n"
703 	".previous"
704 	:"=&r" (temp), "=m" (v->counter), "=&r" (result)
705 	:"Ir" (i), "m" (v->counter) : "memory");
706 	return result;
707 }
708 
atomic_sub_return(int i,atomic_t * v)709 static __inline__ long atomic_sub_return(int i, atomic_t * v)
710 {
711 	long temp, result;
712 	__asm__ __volatile__(
713 	"1:	ldl_l %0,%1\n"
714 	"	subl %0,%3,%2\n"
715 	"	subl %0,%3,%0\n"
716 	"	stl_c %0,%1\n"
717 	"	beq %0,2f\n"
718 	"	mb\n"
719 	".subsection 2\n"
720 	"2:	br 1b\n"
721 	".previous"
722 	:"=&r" (temp), "=m" (v->counter), "=&r" (result)
723 	:"Ir" (i), "m" (v->counter) : "memory");
724 	return result;
725 }
726 
727 #define atomic_dec_return(v) atomic_sub_return(1,(v))
728 #define atomic_inc_return(v) atomic_add_return(1,(v))
729 
730 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
731 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
732 
733 #define atomic_inc(v) atomic_add(1,(v))
734 #define atomic_dec(v) atomic_sub(1,(v))
735 
736 #define smp_mb__before_atomic_dec()	smp_mb()
737 #define smp_mb__after_atomic_dec()	smp_mb()
738 #define smp_mb__before_atomic_inc()	smp_mb()
739 #define smp_mb__after_atomic_inc()	smp_mb()
740 
741 #endif /* _ALPHA_ATOMIC_H */
742 
743 #else
744 
745 #ifdef __s390__
746 
747 #ifndef __ARCH_S390_ATOMIC__
748 #define __ARCH_S390_ATOMIC__
749 
750 /*
751  *  include/asm-s390/atomic.h
752  *
753  *  S390 version
754  *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
755  *    Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
756  *               Denis Joseph Barrow
757  *
758  *  Derived from "include/asm-i386/bitops.h"
759  *    Copyright (C) 1992, Linus Torvalds
760  *
761  */
762 
763 /*
764  * Atomic operations that C can't guarantee us.  Useful for
765  * resource counting etc..
766  * S390 uses 'Compare And Swap' for atomicity in SMP enviroment
767  */
768 
769 typedef struct { volatile int counter; } __attribute__ ((aligned (4))) atomic_t;
770 #define ATOMIC_INIT(i)  { (i) }
771 
772 #define atomic_eieio()          __asm__ __volatile__ ("BCR 15,0")
773 
774 #define __CS_LOOP(old_val, new_val, ptr, op_val, op_string)		\
775         __asm__ __volatile__("   l     %0,0(%2)\n"			\
776                              "0: lr    %1,%0\n"				\
777                              op_string "  %1,%3\n"			\
778                              "   cs    %0,%1,0(%2)\n"			\
779                              "   jl    0b"				\
780                              : "=&d" (old_val), "=&d" (new_val)		\
781 			     : "a" (ptr), "d" (op_val) : "cc" );
782 
783 #define atomic_read(v)          ((v)->counter)
784 #define atomic_set(v,i)         (((v)->counter) = (i))
785 
atomic_add(int i,atomic_t * v)786 static __inline__ void atomic_add(int i, atomic_t *v)
787 {
788 	int old_val, new_val;
789 	__CS_LOOP(old_val, new_val, v, i, "ar");
790 }
791 
atomic_add_return(int i,atomic_t * v)792 static __inline__ int atomic_add_return (int i, atomic_t *v)
793 {
794 	int old_val, new_val;
795 	__CS_LOOP(old_val, new_val, v, i, "ar");
796 	return new_val;
797 }
798 
atomic_add_negative(int i,atomic_t * v)799 static __inline__ int atomic_add_negative(int i, atomic_t *v)
800 {
801 	int old_val, new_val;
802         __CS_LOOP(old_val, new_val, v, i, "ar");
803         return new_val < 0;
804 }
805 
atomic_sub(int i,atomic_t * v)806 static __inline__ void atomic_sub(int i, atomic_t *v)
807 {
808 	int old_val, new_val;
809 	__CS_LOOP(old_val, new_val, v, i, "sr");
810 }
811 
atomic_inc(volatile atomic_t * v)812 static __inline__ void atomic_inc(volatile atomic_t *v)
813 {
814 	int old_val, new_val;
815 	__CS_LOOP(old_val, new_val, v, 1, "ar");
816 }
817 
atomic_inc_return(volatile atomic_t * v)818 static __inline__ int atomic_inc_return(volatile atomic_t *v)
819 {
820 	int old_val, new_val;
821 	__CS_LOOP(old_val, new_val, v, 1, "ar");
822         return new_val;
823 }
824 
atomic_inc_and_test(volatile atomic_t * v)825 static __inline__ int atomic_inc_and_test(volatile atomic_t *v)
826 {
827 	int old_val, new_val;
828 	__CS_LOOP(old_val, new_val, v, 1, "ar");
829 	return new_val != 0;
830 }
831 
atomic_dec(volatile atomic_t * v)832 static __inline__ void atomic_dec(volatile atomic_t *v)
833 {
834 	int old_val, new_val;
835 	__CS_LOOP(old_val, new_val, v, 1, "sr");
836 }
837 
atomic_dec_return(volatile atomic_t * v)838 static __inline__ int atomic_dec_return(volatile atomic_t *v)
839 {
840 	int old_val, new_val;
841 	__CS_LOOP(old_val, new_val, v, 1, "sr");
842         return new_val;
843 }
844 
atomic_dec_and_test(volatile atomic_t * v)845 static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
846 {
847 	int old_val, new_val;
848 	__CS_LOOP(old_val, new_val, v, 1, "sr");
849         return new_val == 0;
850 }
851 
atomic_clear_mask(unsigned long mask,atomic_t * v)852 static __inline__ void atomic_clear_mask(unsigned long mask, atomic_t *v)
853 {
854 	int old_val, new_val;
855 	__CS_LOOP(old_val, new_val, v, ~mask, "nr");
856 }
857 
atomic_set_mask(unsigned long mask,atomic_t * v)858 static __inline__ void atomic_set_mask(unsigned long mask, atomic_t *v)
859 {
860 	int old_val, new_val;
861 	__CS_LOOP(old_val, new_val, v, mask, "or");
862 }
863 
864 /*
865   returns 0  if expected_oldval==value in *v ( swap was successful )
866   returns 1  if unsuccessful.
867 */
868 static __inline__ int
atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t * v)869 atomic_compare_and_swap(int expected_oldval,int new_val,atomic_t *v)
870 {
871         int retval;
872 
873         __asm__ __volatile__(
874                 "  lr   0,%2\n"
875                 "  cs   0,%3,0(%1)\n"
876                 "  ipm  %0\n"
877                 "  srl  %0,28\n"
878                 "0:"
879                 : "=&d" (retval)
880                 : "a" (v), "d" (expected_oldval) , "d" (new_val)
881                 : "0", "cc");
882         return retval;
883 }
884 
885 /*
886   Spin till *v = expected_oldval then swap with newval.
887  */
888 static __inline__ void
atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t * v)889 atomic_compare_and_swap_spin(int expected_oldval,int new_val,atomic_t *v)
890 {
891         __asm__ __volatile__(
892                 "0: lr  0,%1\n"
893                 "   cs  0,%2,0(%0)\n"
894                 "   jl  0b\n"
895                 : : "a" (v), "d" (expected_oldval) , "d" (new_val)
896                 : "cc", "0" );
897 }
898 
899 #define smp_mb__before_atomic_dec()	smp_mb()
900 #define smp_mb__after_atomic_dec()	smp_mb()
901 #define smp_mb__before_atomic_inc()	smp_mb()
902 #define smp_mb__after_atomic_inc()	smp_mb()
903 
904 #endif                                 /* __ARCH_S390_ATOMIC __            */
905 
906 #else
907 
908 #ifdef __mips__
909 
910 /*
911  * Atomic operations that C can't guarantee us.  Useful for
912  * resource counting etc..
913  *
914  * But use these as seldom as possible since they are much more slower
915  * than regular operations.
916  *
917  * This file is subject to the terms and conditions of the GNU General Public
918  * License.  See the file "COPYING" in the main directory of this archive
919  * for more details.
920  *
921  * Copyright (C) 1996, 1997, 2000 by Ralf Baechle
922  */
923 #ifndef __ASM_ATOMIC_H
924 #define __ASM_ATOMIC_H
925 
926 typedef struct { volatile int counter; } atomic_t;
927 
928 #define ATOMIC_INIT(i)    { (i) }
929 
930 /*
931  * atomic_read - read atomic variable
932  * @v: pointer of type atomic_t
933  *
934  * Atomically reads the value of @v.  Note that the guaranteed
935  * useful range of an atomic_t is only 24 bits.
936  */
937 #define atomic_read(v)	((v)->counter)
938 
939 /*
940  * atomic_set - set atomic variable
941  * @v: pointer of type atomic_t
942  * @i: required value
943  *
944  * Atomically sets the value of @v to @i.  Note that the guaranteed
945  * useful range of an atomic_t is only 24 bits.
946  */
947 #define atomic_set(v,i)	((v)->counter = (i))
948 
949 /*
950  * ... while for MIPS II and better we can use ll/sc instruction.  This
951  * implementation is SMP safe ...
952  */
953 
954 /*
955  * atomic_add - add integer to atomic variable
956  * @i: integer value to add
957  * @v: pointer of type atomic_t
958  *
959  * Atomically adds @i to @v.  Note that the guaranteed useful range
960  * of an atomic_t is only 24 bits.
961  */
atomic_add(int i,atomic_t * v)962 extern __inline__ void atomic_add(int i, atomic_t * v)
963 {
964 	unsigned long temp;
965 
966 	__asm__ __volatile__(
967 		".set push                # atomic_add\n"
968 		".set mips2                           \n"
969 		"1:   ll      %0, %1                  \n"
970 		"     addu    %0, %2                  \n"
971 		"     sc      %0, %1                  \n"
972 		"     beqz    %0, 1b                  \n"
973 		".set pop                             \n"
974 		: "=&r" (temp), "=m" (v->counter)
975 		: "Ir" (i), "m" (v->counter));
976 }
977 
978 /*
979  * atomic_sub - subtract the atomic variable
980  * @i: integer value to subtract
981  * @v: pointer of type atomic_t
982  *
983  * Atomically subtracts @i from @v.  Note that the guaranteed
984  * useful range of an atomic_t is only 24 bits.
985  */
atomic_sub(int i,atomic_t * v)986 extern __inline__ void atomic_sub(int i, atomic_t * v)
987 {
988 	unsigned long temp;
989 
990 	__asm__ __volatile__(
991 		".set push                # atomic_sub\n"
992 		".set mips2                           \n"
993 		"1:   ll      %0, %1                  \n"
994 		"     subu    %0, %2                  \n"
995 		"     sc      %0, %1                  \n"
996 		"     beqz    %0, 1b                  \n"
997 		".set pop                             \n"
998 		: "=&r" (temp), "=m" (v->counter)
999 		: "Ir" (i), "m" (v->counter));
1000 }
1001 
1002 /*
1003  * Same as above, but return the result value
1004  */
atomic_add_return(int i,atomic_t * v)1005 extern __inline__ int atomic_add_return(int i, atomic_t * v)
1006 {
1007 	unsigned long temp, result;
1008 
1009 	__asm__ __volatile__(
1010 		".set push               # atomic_add_return\n"
1011 		".set mips2                                 \n"
1012 		".set noreorder                             \n"
1013 		"1:   ll      %1, %2                        \n"
1014 		"     addu    %0, %1, %3                    \n"
1015 		"     sc      %0, %2                        \n"
1016 		"     beqz    %0, 1b                        \n"
1017 		"     addu    %0, %1, %3                    \n"
1018 		"     sync                                  \n"
1019 		".set pop                                   \n"
1020 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
1021 		: "Ir" (i), "m" (v->counter)
1022 		: "memory");
1023 
1024 	return result;
1025 }
1026 
atomic_sub_return(int i,atomic_t * v)1027 extern __inline__ int atomic_sub_return(int i, atomic_t * v)
1028 {
1029 	unsigned long temp, result;
1030 
1031 	__asm__ __volatile__(
1032 		".set push                # atomic_sub_return\n"
1033 		".set mips2                                  \n"
1034 		".set noreorder                              \n"
1035 		"1:   ll    %1, %2                           \n"
1036 		"     subu  %0, %1, %3                       \n"
1037 		"     sc    %0, %2                           \n"
1038 		"     beqz  %0, 1b                           \n"
1039 		"     subu  %0, %1, %3                       \n"
1040 		"     sync                                   \n"
1041 		".set pop                                    \n"
1042 		: "=&r" (result), "=&r" (temp), "=m" (v->counter)
1043 		: "Ir" (i), "m" (v->counter)
1044 		: "memory");
1045 
1046 	return result;
1047 }
1048 
1049 #define atomic_dec_return(v) atomic_sub_return(1,(v))
1050 #define atomic_inc_return(v) atomic_add_return(1,(v))
1051 
1052 /*
1053  * atomic_sub_and_test - subtract value from variable and test result
1054  * @i: integer value to subtract
1055  * @v: pointer of type atomic_t
1056  *
1057  * Atomically subtracts @i from @v and returns
1058  * true if the result is zero, or false for all
1059  * other cases.  Note that the guaranteed
1060  * useful range of an atomic_t is only 24 bits.
1061  */
1062 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
1063 
1064 /*
1065  * atomic_inc_and_test - increment and test
1066  * @v: pointer of type atomic_t
1067  *
1068  * Atomically increments @v by 1
1069  * and returns true if the result is zero, or false for all
1070  * other cases.  Note that the guaranteed
1071  * useful range of an atomic_t is only 24 bits.
1072  */
1073 #define atomic_inc_and_test(v) (atomic_inc_return(1, (v)) == 0)
1074 
1075 /*
1076  * atomic_dec_and_test - decrement by 1 and test
1077  * @v: pointer of type atomic_t
1078  *
1079  * Atomically decrements @v by 1 and
1080  * returns true if the result is 0, or false for all other
1081  * cases.  Note that the guaranteed
1082  * useful range of an atomic_t is only 24 bits.
1083  */
1084 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
1085 
1086 /*
1087  * atomic_inc - increment atomic variable
1088  * @v: pointer of type atomic_t
1089  *
1090  * Atomically increments @v by 1.  Note that the guaranteed
1091  * useful range of an atomic_t is only 24 bits.
1092  */
1093 #define atomic_inc(v) atomic_add(1,(v))
1094 
1095 /*
1096  * atomic_dec - decrement and test
1097  * @v: pointer of type atomic_t
1098  *
1099  * Atomically decrements @v by 1.  Note that the guaranteed
1100  * useful range of an atomic_t is only 24 bits.
1101  */
1102 #define atomic_dec(v) atomic_sub(1,(v))
1103 
1104 /*
1105  * atomic_add_negative - add and test if negative
1106  * @v: pointer of type atomic_t
1107  * @i: integer value to add
1108  *
1109  * Atomically adds @i to @v and returns true
1110  * if the result is negative, or false when
1111  * result is greater than or equal to zero.  Note that the guaranteed
1112  * useful range of an atomic_t is only 24 bits.
1113  *
1114  * Currently not implemented for MIPS.
1115  */
1116 
1117 /* Atomic operations are already serializing */
1118 #define smp_mb__before_atomic_dec()	smp_mb()
1119 #define smp_mb__after_atomic_dec()	smp_mb()
1120 #define smp_mb__before_atomic_inc()	smp_mb()
1121 #define smp_mb__after_atomic_inc()	smp_mb()
1122 
1123 #endif /* __ASM_ATOMIC_H */
1124 
1125 #else
1126 
1127 #if defined(__m68k__)
1128 
1129 #ifndef __ARCH_M68K_ATOMIC__
1130 #define __ARCH_M68K_ATOMIC__
1131 
1132 /*
1133  * Atomic operations that C can't guarantee us.  Useful for
1134  * resource counting etc..
1135  */
1136 
1137 /*
1138  * We do not have SMP m68k systems, so we don't have to deal with that.
1139  */
1140 
1141 typedef struct { int counter; } atomic_t;
1142 #define ATOMIC_INIT(i)	{ (i) }
1143 
1144 #define atomic_read(v)		((v)->counter)
1145 #define atomic_set(v, i)	(((v)->counter) = i)
1146 
atomic_add(int i,atomic_t * v)1147 static __inline__ void atomic_add(int i, atomic_t *v)
1148 {
1149 	__asm__ __volatile__("addl %1,%0" : "=m" (*v) : "id" (i), "0" (*v));
1150 }
1151 
atomic_sub(int i,atomic_t * v)1152 static __inline__ void atomic_sub(int i, atomic_t *v)
1153 {
1154 	__asm__ __volatile__("subl %1,%0" : "=m" (*v) : "id" (i), "0" (*v));
1155 }
1156 
atomic_inc(volatile atomic_t * v)1157 static __inline__ void atomic_inc(volatile atomic_t *v)
1158 {
1159 	__asm__ __volatile__("addql #1,%0" : "=m" (*v): "0" (*v));
1160 }
1161 
atomic_dec(volatile atomic_t * v)1162 static __inline__ void atomic_dec(volatile atomic_t *v)
1163 {
1164 	__asm__ __volatile__("subql #1,%0" : "=m" (*v): "0" (*v));
1165 }
1166 
atomic_dec_and_test(volatile atomic_t * v)1167 static __inline__ int atomic_dec_and_test(volatile atomic_t *v)
1168 {
1169 	char c;
1170 	__asm__ __volatile__("subql #1,%1; seq %0" : "=d" (c), "=m" (*v): "1" (*v));
1171 	return c != 0;
1172 }
1173 
1174 #define atomic_clear_mask(mask, v) \
1175 	__asm__ __volatile__("andl %1,%0" : "=m" (*v) : "id" (~(mask)),"0"(*v))
1176 
1177 #define atomic_set_mask(mask, v) \
1178 	__asm__ __volatile__("orl %1,%0" : "=m" (*v) : "id" (mask),"0"(*v))
1179 
1180 /* Atomic operations are already serializing */
1181 #define smp_mb__before_atomic_dec()	barrier()
1182 #define smp_mb__after_atomic_dec()	barrier()
1183 #define smp_mb__before_atomic_inc()	barrier()
1184 #define smp_mb__after_atomic_inc()	barrier()
1185 
1186 #endif /* __ARCH_M68K_ATOMIC __ */
1187 
1188 #else
1189 
1190 #warning libs/pbd has no implementation of strictly atomic operations for your hardware.
1191 
1192 #define __NO_STRICT_ATOMIC
1193 #ifdef __NO_STRICT_ATOMIC
1194 
1195 /*
1196  * Because the implementations from the kernel (where all these come
1197  * from) use cli and spinlocks for hppa and arm...
1198  */
1199 
1200 typedef struct { volatile int counter; } atomic_t;
1201 
1202 #define ATOMIC_INIT(i)	( (atomic_t) { (i) } )
1203 
1204 #define atomic_read(v)		((v)->counter)
1205 #define atomic_set(v,i)		((v)->counter = (i))
1206 
atomic_inc(atomic_t * v)1207 static __inline__ void atomic_inc(atomic_t *v)
1208 {
1209 	v->counter++;
1210 }
1211 
atomic_dec(atomic_t * v)1212 static __inline__ void atomic_dec(atomic_t *v)
1213 {
1214 	v->counter--;
1215 }
1216 
atomic_dec_and_test(atomic_t * v)1217 static __inline__ int atomic_dec_and_test(atomic_t *v)
1218 {
1219 	int res;
1220 	v->counter--;
1221 	res = v->counter;
1222 	return res == 0;
1223 }
1224 
atomic_inc_and_test(atomic_t * v)1225 static __inline__ int atomic_inc_and_test(atomic_t *v)
1226 {
1227 	int res;
1228 	v->counter++;
1229 	res = v->counter;
1230 	return res == 0;
1231 }
1232 
1233 #  endif /* __NO_STRICT_ATOMIC */
1234 #  endif /* m68k */
1235 #  endif /* mips */
1236 #  endif /* s390 */
1237 #  endif /* alpha */
1238 #  endif /* ia64 */
1239 #  endif /* sparc */
1240 #  endif /* i386 */
1241 #  endif /* ppc */
1242 
1243 /***********************************************************************/
1244 
1245 #else   /* !linux */
1246 
1247 typedef unsigned long atomic_t;
1248 
1249 #if defined(__sgi)
1250 #undef atomic_set
1251 #endif
1252 
1253 inline
1254 void
atomic_set(atomic_t * a,int v)1255 atomic_set (atomic_t * a, int v) {
1256 #if defined(__sgi) && !defined(__GNUC__)
1257 	__lock_test_and_set(a, v);
1258 #else
1259 	*a=v;
1260 #endif
1261 }
1262 
1263 inline
1264 int
atomic_read(const atomic_t * a)1265 atomic_read (const atomic_t * a) {
1266 	return *a;
1267 }
1268 
1269 inline
1270 void
atomic_inc(atomic_t * a)1271 atomic_inc (atomic_t * a) {
1272 #if defined(__sgi) && !defined(__GNUC__)
1273 	__add_and_fetch(a, 1);
1274 #else
1275 	++(*a);
1276 #endif
1277 }
1278 
1279 inline
1280 void
atomic_dec(atomic_t * a)1281 atomic_dec (atomic_t * a) {
1282 #if defined(__sgi) && !defined(__GNUC__)
1283 	__sub_and_fetch(a, 1);
1284 #else
1285 	--(*a);
1286 #endif
1287 }
1288 
1289 #endif /* linux */
1290 #endif /* __linuxsampler_atomic_h__ */
1291