1#ifndef _ASM_GENERIC_BITOPS_ATOMIC_H_
2#define _ASM_GENERIC_BITOPS_ATOMIC_H_
3
4#include <asm/types.h>
5#include <asm/system.h>
6
7#ifdef CONFIG_SMP
8#include <asm/spinlock.h>
9#include <asm/cache.h>
10
11
12
13
14
15# define ATOMIC_HASH_SIZE 4
16# define ATOMIC_HASH(a) (&(__atomic_hash[ (((unsigned long) a)/L1_CACHE_BYTES) & (ATOMIC_HASH_SIZE-1) ]))
17
18extern raw_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned;
19
20
21
22#define _atomic_spin_lock_irqsave(l,f) do { \
23 raw_spinlock_t *s = ATOMIC_HASH(l); \
24 local_irq_save(f); \
25 __raw_spin_lock(s); \
26} while(0)
27
28#define _atomic_spin_unlock_irqrestore(l,f) do { \
29 raw_spinlock_t *s = ATOMIC_HASH(l); \
30 __raw_spin_unlock(s); \
31 local_irq_restore(f); \
32} while(0)
33
34
35#else
36# define _atomic_spin_lock_irqsave(l,f) do { local_irq_save(f); } while (0)
37# define _atomic_spin_unlock_irqrestore(l,f) do { local_irq_restore(f); } while (0)
38#endif
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65static inline void set_bit(int nr, volatile unsigned long *addr)
66{
67 unsigned long mask = BIT_MASK(nr);
68 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
69 unsigned long flags;
70
71 _atomic_spin_lock_irqsave(p, flags);
72 *p |= mask;
73 _atomic_spin_unlock_irqrestore(p, flags);
74}
75
76
77
78
79
80
81
82
83
84
85
86static inline void clear_bit(int nr, volatile unsigned long *addr)
87{
88 unsigned long mask = BIT_MASK(nr);
89 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
90 unsigned long flags;
91
92 _atomic_spin_lock_irqsave(p, flags);
93 *p &= ~mask;
94 _atomic_spin_unlock_irqrestore(p, flags);
95}
96
97
98
99
100
101
102
103
104
105
106
107static inline void change_bit(int nr, volatile unsigned long *addr)
108{
109 unsigned long mask = BIT_MASK(nr);
110 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
111 unsigned long flags;
112
113 _atomic_spin_lock_irqsave(p, flags);
114 *p ^= mask;
115 _atomic_spin_unlock_irqrestore(p, flags);
116}
117
118
119
120
121
122
123
124
125
126
127static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
128{
129 unsigned long mask = BIT_MASK(nr);
130 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
131 unsigned long old;
132 unsigned long flags;
133
134 _atomic_spin_lock_irqsave(p, flags);
135 old = *p;
136 *p = old | mask;
137 _atomic_spin_unlock_irqrestore(p, flags);
138
139 return (old & mask) != 0;
140}
141
142
143
144
145
146
147
148
149
150
151static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
152{
153 unsigned long mask = BIT_MASK(nr);
154 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
155 unsigned long old;
156 unsigned long flags;
157
158 _atomic_spin_lock_irqsave(p, flags);
159 old = *p;
160 *p = old & ~mask;
161 _atomic_spin_unlock_irqrestore(p, flags);
162
163 return (old & mask) != 0;
164}
165
166
167
168
169
170
171
172
173
174static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
175{
176 unsigned long mask = BIT_MASK(nr);
177 unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
178 unsigned long old;
179 unsigned long flags;
180
181 _atomic_spin_lock_irqsave(p, flags);
182 old = *p;
183 *p = old ^ mask;
184 _atomic_spin_unlock_irqrestore(p, flags);
185
186 return (old & mask) != 0;
187}
188
189#endif
190