1 /* atomic.h: These still suck, but the I-cache hit rate is higher.
2 *
3 * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
4 */
5
6 #ifndef __ARCH_SPARC_ATOMIC__
7 #define __ARCH_SPARC_ATOMIC__
8
9 #include <linux/config.h>
10
11 typedef struct { volatile int counter; } atomic_t;
12
13 #ifdef __KERNEL__
14 #ifndef CONFIG_SMP
15
16 #define ATOMIC_INIT(i) { (i) }
17 #define atomic_read(v) ((v)->counter)
18 #define atomic_set(v, i) (((v)->counter) = i)
19
20 #else
21 /* We do the bulk of the actual work out of line in two common
22 * routines in assembler, see arch/sparc/lib/atomic.S for the
23 * "fun" details.
24 *
25 * For SMP the trick is you embed the spin lock byte within
26 * the word, use the low byte so signedness is easily retained
27 * via a quick arithmetic shift. It looks like this:
28 *
29 * ----------------------------------------
30 * | signed 24-bit counter value | lock | atomic_t
31 * ----------------------------------------
32 * 31 8 7 0
33 */
34
35 #define ATOMIC_INIT(i) { (i << 8) }
36
37 static __inline__ int atomic_read(atomic_t *v)
38 {
39 int ret = v->counter;
40
41 while(ret & 0xff)
42 ret = v->counter;
43
44 return ret >> 8;
45 }
46
47 #define atomic_set(v, i) (((v)->counter) = ((i) << 8))
48 #endif
49
50 /* Make sure gcc doesn't try to be clever and move things around
51 * on us. We need to use _exactly_ the address the user gave us,
52 * not some alias that contains the same information.
53 */
54 #define __atomic_fool_gcc(x) ((struct { int a[100]; } *)x)
55
56 static __inline__ void atomic_add(int i, atomic_t *v)
57 {
58 register atomic_t *ptr asm("g1");
59 register int increment asm("g2");
60 ptr = (atomic_t *) __atomic_fool_gcc(v);
61 increment = i;
62
63 __asm__ __volatile__("
64 mov %%o7, %%g4
65 call ___atomic_add
66 add %%o7, 8, %%o7
67 " : "=&r" (increment)
68 : "" (increment), "r" (ptr)
69 : "g3", "g4", "g7", "memory", "cc");
70 }
71
72 static __inline__ void atomic_sub(int i, atomic_t *v)
73 {
74 register atomic_t *ptr asm("g1");
75 register int increment asm("g2");
76
77 ptr = (atomic_t *) __atomic_fool_gcc(v);
78 increment = i;
79
80 __asm__ __volatile__("
81 mov %%o7, %%g4
82 call ___atomic_sub
83 add %%o7, 8, %%o7
84 " : "=&r" (increment)
85 : "" (increment), "r" (ptr)
86 : "g3", "g4", "g7", "memory", "cc");
87 }
88
89 static __inline__ int atomic_add_return(int i, atomic_t *v)
90 {
91 register atomic_t *ptr asm("g1");
92 register int increment asm("g2");
93
94 ptr = (atomic_t *) __atomic_fool_gcc(v);
95 increment = i;
96
97 __asm__ __volatile__("
98 mov %%o7, %%g4
99 call ___atomic_add
100 add %%o7, 8, %%o7
101 " : "=&r" (increment)
102 : "" (increment), "r" (ptr)
103 : "g3", "g4", "g7", "memory", "cc");
104
105 return increment;
106 }
107
108 static __inline__ int atomic_sub_return(int i, atomic_t *v)
109 {
110 register atomic_t *ptr asm("g1");
111 register int increment asm("g2");
112
113 ptr = (atomic_t *) __atomic_fool_gcc(v);
114 increment = i;
115
116 __asm__ __volatile__("
117 mov %%o7, %%g4
118 call ___atomic_sub
119 add %%o7, 8, %%o7
120 " : "=&r" (increment)
121 : "" (increment), "r" (ptr)
122 : "g3", "g4", "g7", "memory", "cc");
123
124 return increment;
125 }
126
127 #define atomic_dec_return(v) atomic_sub_return(1,(v))
128 #define atomic_inc_return(v) atomic_add_return(1,(v))
129
130 #define atomic_sub_and_test(i, v) (atomic_sub_return((i), (v)) == 0)
131 #define atomic_dec_and_test(v) (atomic_sub_return(1, (v)) == 0)
132
133 #define atomic_inc(v) atomic_add(1,(v))
134 #define atomic_dec(v) atomic_sub(1,(v))
135
136 #define atomic_add_negative(i, v) (atomic_add_return((i), (v)) < 0)
137
138 #endif /* !(__KERNEL__) */
139
140 #endif /* !(__ARCH_SPARC_ATOMIC__) */
141
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.