1 #ifndef _PARISC_BITOPS_H
2 #define _PARISC_BITOPS_H
3
4 #include <linux/spinlock.h>
5 #include <asm/system.h>
6 #include <asm/byteorder.h>
7 #include <asm/atomic.h>
8
9 #ifdef __LP64__
10 # define SHIFT_PER_LONG 6
11 #ifndef BITS_PER_LONG
12 # define BITS_PER_LONG 64
13 #endif
14 #else
15 # define SHIFT_PER_LONG 5
16 #ifndef BITS_PER_LONG
17 # define BITS_PER_LONG 32
18 #endif
19 #endif
20
21 #define CHOP_SHIFTCOUNT(x) ((x) & (BITS_PER_LONG - 1))
22
23 static __inline__ int test_and_set_bit(int nr, void * address)
24 {
25 unsigned long mask;
26 unsigned long *addr = (unsigned long *) address;
27 int oldbit;
28 unsigned long flags;
29
30 addr += (nr >> SHIFT_PER_LONG);
31 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
32
33 mask = 1L << CHOP_SHIFTCOUNT(nr);
34 oldbit = (*addr & mask) ? 1 : 0;
35 *addr |= mask;
36
37 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
38
39 return oldbit;
40 }
41
42 static __inline__ int test_and_clear_bit(int nr, void * address)
43 {
44 unsigned long mask;
45 unsigned long *addr = (unsigned long *) address;
46 int oldbit;
47 unsigned long flags;
48
49 addr += (nr >> SHIFT_PER_LONG);
50 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
51
52 mask = 1L << CHOP_SHIFTCOUNT(nr);
53 oldbit = (*addr & mask) ? 1 : 0;
54 *addr &= ~mask;
55
56 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
57
58 return oldbit;
59 }
60
61 static __inline__ int test_and_change_bit(int nr, void * address)
62 {
63 unsigned long mask;
64 unsigned long *addr = (unsigned long *) address;
65 int oldbit;
66 unsigned long flags;
67
68 addr += (nr >> SHIFT_PER_LONG);
69 SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
70
71 mask = 1L << CHOP_SHIFTCOUNT(nr);
72 oldbit = (*addr & mask) ? 1 : 0;
73 *addr ^= mask;
74
75 SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
76
77 return oldbit;
78 }
79
80 /* again, the read-only case doesn't have to do any locking */
81
82 static __inline__ int test_bit(int nr, const volatile void *address)
83 {
84 unsigned long mask;
85 unsigned long *addr = (unsigned long *) address;
86
87 addr += (nr >> SHIFT_PER_LONG);
88 mask = 1L << CHOP_SHIFTCOUNT(nr);
89
90 return !!(*addr & mask);
91 }
92
93 /* sparc does this, other arch's don't -- what's the right answer? XXX */
94 #define smp_mb__before_clear_bit() do { } while(0)
95 #define smp_mb__after_clear_bit() do { } while(0)
96 #define set_bit(nr,addr) ((void)test_and_set_bit(nr,addr))
97 #define clear_bit(nr,addr) ((void)test_and_clear_bit(nr,addr))
98 #define change_bit(nr,addr) ((void)test_and_change_bit(nr,addr))
99
100 /* XXX We'd need some binary search here */
101
102 extern __inline__ unsigned long ffz(unsigned long word)
103 {
104 unsigned long result;
105
106 result = 0;
107 while(word & 1) {
108 result++;
109 word >>= 1;
110 }
111
112 return result;
113 }
114
115 #ifdef __KERNEL__
116
117 /*
118 * ffs: find first bit set. This is defined the same way as
119 * the libc and compiler builtin ffs routines, therefore
120 * differs in spirit from the above ffz (man ffs).
121 */
122
123 #define ffs(x) generic_ffs(x)
124
125 /*
126 * hweightN: returns the hamming weight (i.e. the number
127 * of bits set) of a N-bit word
128 */
129
130 #define hweight32(x) generic_hweight32(x)
131 #define hweight16(x) generic_hweight16(x)
132 #define hweight8(x) generic_hweight8(x)
133
134 #endif /* __KERNEL__ */
135
136 /*
137 * This implementation of find_{first,next}_zero_bit was stolen from
138 * Linus' asm-alpha/bitops.h.
139 */
140 #define find_first_zero_bit(addr, size) \
141 find_next_zero_bit((addr), (size), 0)
142
143 static __inline__ unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
144 {
145 unsigned long * p = ((unsigned long *) addr) + (offset >> SHIFT_PER_LONG);
146 unsigned long result = offset & ~(BITS_PER_LONG-1);
147 unsigned long tmp;
148
149 if (offset >= size)
150 return size;
151 size -= result;
152 offset &= (BITS_PER_LONG-1);
153 if (offset) {
154 tmp = *(p++);
155 tmp |= ~0UL >> (BITS_PER_LONG-offset);
156 if (size < BITS_PER_LONG)
157 goto found_first;
158 if (~tmp)
159 goto found_middle;
160 size -= BITS_PER_LONG;
161 result += BITS_PER_LONG;
162 }
163 while (size & ~(BITS_PER_LONG -1)) {
164 if (~(tmp = *(p++)))
165 goto found_middle;
166 result += BITS_PER_LONG;
167 size -= BITS_PER_LONG;
168 }
169 if (!size)
170 return result;
171 tmp = *p;
172 found_first:
173 tmp |= ~0UL << size;
174 found_middle:
175 return result + ffz(tmp);
176 }
177
178 #define _EXT2_HAVE_ASM_BITOPS_
179
180 #ifdef __KERNEL__
181 /*
182 * test_and_{set,clear}_bit guarantee atomicity without
183 * disabling interrupts.
184 */
185 #define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr)
186 #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr)
187
188 #endif /* __KERNEL__ */
189
190 static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
191 {
192 __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
193
194 return (ADDR[nr >> 3] >> (nr & 7)) & 1;
195 }
196
197 /*
198 * This implementation of ext2_find_{first,next}_zero_bit was stolen from
199 * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
200 */
201
202 #define ext2_find_first_zero_bit(addr, size) \
203 ext2_find_next_zero_bit((addr), (size), 0)
204
205 extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
206 unsigned long size, unsigned long offset)
207 {
208 unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
209 unsigned int result = offset & ~31UL;
210 unsigned int tmp;
211
212 if (offset >= size)
213 return size;
214 size -= result;
215 offset &= 31UL;
216 if (offset) {
217 tmp = cpu_to_le32p(p++);
218 tmp |= ~0UL >> (32-offset);
219 if (size < 32)
220 goto found_first;
221 if (tmp != ~0U)
222 goto found_middle;
223 size -= 32;
224 result += 32;
225 }
226 while (size >= 32) {
227 if ((tmp = cpu_to_le32p(p++)) != ~0U)
228 goto found_middle;
229 result += 32;
230 size -= 32;
231 }
232 if (!size)
233 return result;
234 tmp = cpu_to_le32p(p);
235 found_first:
236 tmp |= ~0U << size;
237 found_middle:
238 return result + ffz(tmp);
239 }
240
241 /* Bitmap functions for the minix filesystem. */
242 #define minix_set_bit(nr,addr) ext2_set_bit(nr,addr)
243 #define minix_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
244 #define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
245 #define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
246
247 #endif /* _PARISC_BITOPS_H */
248
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.