cleanup
[linux-2.4.21-pre4.git] / include / asm-alpha / atomic.h
1 #ifndef _ALPHA_ATOMIC_H
2 #define _ALPHA_ATOMIC_H
3
4 /*
5  * Atomic operations that C can't guarantee us.  Useful for
6  * resource counting etc...
7  *
8  * But use these as seldom as possible since they are much slower
9  * than regular operations.
10  */
11
12
13 /*
14  * Counter is volatile to make sure gcc doesn't try to be clever
15  * and move things around on us. We need to use _exactly_ the address
16  * the user gave us, not some alias that contains the same information.
17  */
18 typedef struct { volatile int counter; } atomic_t;
19
20 #define ATOMIC_INIT(i)  ( (atomic_t) { (i) } )
21
22 #define atomic_read(v)          ((v)->counter)
23 #define atomic_set(v,i)         ((v)->counter = (i))
24
25 /*
26  * To get proper branch prediction for the main line, we must branch
27  * forward to code at the end of this object's .text section, then
28  * branch back to restart the operation.
29  */
30
31 static __inline__ void atomic_add(int i, atomic_t * v)
32 {
33         unsigned long temp;
34         __asm__ __volatile__(
35         "1:     ldl_l %0,%1\n"
36         "       addl %0,%2,%0\n"
37         "       stl_c %0,%1\n"
38         "       beq %0,2f\n"
39         ".subsection 2\n"
40         "2:     br 1b\n"
41         ".previous"
42         :"=&r" (temp), "=m" (v->counter)
43         :"Ir" (i), "m" (v->counter));
44 }
45
46 static __inline__ void atomic_sub(int i, atomic_t * v)
47 {
48         unsigned long temp;
49         __asm__ __volatile__(
50         "1:     ldl_l %0,%1\n"
51         "       subl %0,%2,%0\n"
52         "       stl_c %0,%1\n"
53         "       beq %0,2f\n"
54         ".subsection 2\n"
55         "2:     br 1b\n"
56         ".previous"
57         :"=&r" (temp), "=m" (v->counter)
58         :"Ir" (i), "m" (v->counter));
59 }
60
61 /*
62  * Same as above, but return the result value
63  */
64 static __inline__ long atomic_add_return(int i, atomic_t * v)
65 {
66         long temp, result;
67         __asm__ __volatile__(
68         "1:     ldl_l %0,%1\n"
69         "       addl %0,%3,%2\n"
70         "       addl %0,%3,%0\n"
71         "       stl_c %0,%1\n"
72         "       beq %0,2f\n"
73         "       mb\n"
74         ".subsection 2\n"
75         "2:     br 1b\n"
76         ".previous"
77         :"=&r" (temp), "=m" (v->counter), "=&r" (result)
78         :"Ir" (i), "m" (v->counter) : "memory");
79         return result;
80 }
81
82 static __inline__ long atomic_sub_return(int i, atomic_t * v)
83 {
84         long temp, result;
85         __asm__ __volatile__(
86         "1:     ldl_l %0,%1\n"
87         "       subl %0,%3,%2\n"
88         "       subl %0,%3,%0\n"
89         "       stl_c %0,%1\n"
90         "       beq %0,2f\n"
91         "       mb\n"
92         ".subsection 2\n"
93         "2:     br 1b\n"
94         ".previous"
95         :"=&r" (temp), "=m" (v->counter), "=&r" (result)
96         :"Ir" (i), "m" (v->counter) : "memory");
97         return result;
98 }
99
100 #define atomic_dec_return(v) atomic_sub_return(1,(v))
101 #define atomic_inc_return(v) atomic_add_return(1,(v))
102
103 #define atomic_sub_and_test(i,v) (atomic_sub_return((i), (v)) == 0)
104 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
105
106 #define atomic_inc(v) atomic_add(1,(v))
107 #define atomic_dec(v) atomic_sub(1,(v))
108
109 #define smp_mb__before_atomic_dec()     smp_mb()
110 #define smp_mb__after_atomic_dec()      smp_mb()
111 #define smp_mb__before_atomic_inc()     smp_mb()
112 #define smp_mb__after_atomic_inc()      smp_mb()
113
114 #endif /* _ALPHA_ATOMIC_H */