~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/include/asm-i386/bitops.h

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 #ifndef _I386_BITOPS_H
  2 #define _I386_BITOPS_H
  3 
  4 /*
  5  * Copyright 1992, Linus Torvalds.
  6  */
  7 
  8 #include <linux/config.h>
  9 
 10 /*
 11  * These have to be done with inline assembly: that way the bit-setting
 12  * is guaranteed to be atomic. All bit operations return 0 if the bit
 13  * was cleared before the operation and != 0 if it was not.
 14  *
 15  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
 16  */
 17 
 18 #ifdef CONFIG_SMP
 19 #define LOCK_PREFIX "lock ; "
 20 #else
 21 #define LOCK_PREFIX ""
 22 #endif
 23 
 24 #define ADDR (*(volatile long *) addr)
 25 
 26 static __inline__ void set_bit(int nr, volatile void * addr)
 27 {
 28         __asm__ __volatile__( LOCK_PREFIX
 29                 "btsl %1,%0"
 30                 :"=m" (ADDR)
 31                 :"Ir" (nr));
 32 }
 33 
 34 /* WARNING: non atomic and it can be reordered! */
 35 static __inline__ void __set_bit(int nr, volatile void * addr)
 36 {
 37         __asm__(
 38                 "btsl %1,%0"
 39                 :"=m" (ADDR)
 40                 :"Ir" (nr));
 41 }
 42 
 43 /*
 44  * clear_bit() doesn't provide any barrier for the compiler.
 45  */
 46 #define smp_mb__before_clear_bit()      barrier()
 47 #define smp_mb__after_clear_bit()       barrier()
 48 static __inline__ void clear_bit(int nr, volatile void * addr)
 49 {
 50         __asm__ __volatile__( LOCK_PREFIX
 51                 "btrl %1,%0"
 52                 :"=m" (ADDR)
 53                 :"Ir" (nr));
 54 }
 55 
 56 static __inline__ void change_bit(int nr, volatile void * addr)
 57 {
 58         __asm__ __volatile__( LOCK_PREFIX
 59                 "btcl %1,%0"
 60                 :"=m" (ADDR)
 61                 :"Ir" (nr));
 62 }
 63 
 64 /*
 65  * It will also imply a memory barrier, thus it must clobber memory
 66  * to make sure to reload anything that was cached into registers
 67  * outside _this_ critical section.
 68  */
 69 static __inline__ int test_and_set_bit(int nr, volatile void * addr)
 70 {
 71         int oldbit;
 72 
 73         __asm__ __volatile__( LOCK_PREFIX
 74                 "btsl %2,%1\n\tsbbl %0,%0"
 75                 :"=r" (oldbit),"=m" (ADDR)
 76                 :"Ir" (nr) : "memory");
 77         return oldbit;
 78 }
 79 
 80 /* WARNING: non atomic and it can be reordered! */
 81 static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
 82 {
 83         int oldbit;
 84 
 85         __asm__(
 86                 "btsl %2,%1\n\tsbbl %0,%0"
 87                 :"=r" (oldbit),"=m" (ADDR)
 88                 :"Ir" (nr));
 89         return oldbit;
 90 }
 91 
 92 static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
 93 {
 94         int oldbit;
 95 
 96         __asm__ __volatile__( LOCK_PREFIX
 97                 "btrl %2,%1\n\tsbbl %0,%0"
 98                 :"=r" (oldbit),"=m" (ADDR)
 99                 :"Ir" (nr) : "memory");
100         return oldbit;
101 }
102 
103 /* WARNING: non atomic and it can be reordered! */
104 static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
105 {
106         int oldbit;
107 
108         __asm__(
109                 "btrl %2,%1\n\tsbbl %0,%0"
110                 :"=r" (oldbit),"=m" (ADDR)
111                 :"Ir" (nr));
112         return oldbit;
113 }
114 
115 static __inline__ int test_and_change_bit(int nr, volatile void * addr)
116 {
117         int oldbit;
118 
119         __asm__ __volatile__( LOCK_PREFIX
120                 "btcl %2,%1\n\tsbbl %0,%0"
121                 :"=r" (oldbit),"=m" (ADDR)
122                 :"Ir" (nr) : "memory");
123         return oldbit;
124 }
125 
126 /*
127  * This routine doesn't need to be atomic.
128  */
129 static __inline__ int constant_test_bit(int nr, const volatile void * addr)
130 {
131         return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
132 }
133 
134 static __inline__ int variable_test_bit(int nr, volatile void * addr)
135 {
136         int oldbit;
137 
138         __asm__ __volatile__(
139                 "btl %2,%1\n\tsbbl %0,%0"
140                 :"=r" (oldbit)
141                 :"m" (ADDR),"Ir" (nr));
142         return oldbit;
143 }
144 
145 #define test_bit(nr,addr) \
146 (__builtin_constant_p(nr) ? \
147  constant_test_bit((nr),(addr)) : \
148  variable_test_bit((nr),(addr)))
149 
150 /*
151  * Find-bit routines..
152  */
153 static __inline__ int find_first_zero_bit(void * addr, unsigned size)
154 {
155         int d0, d1, d2;
156         int res;
157 
158         if (!size)
159                 return 0;
160         /* This looks at memory. Mark it volatile to tell gcc not to move it around */
161         __asm__ __volatile__(
162                 "movl $-1,%%eax\n\t"
163                 "xorl %%edx,%%edx\n\t"
164                 "repe; scasl\n\t"
165                 "je 1f\n\t"
166                 "xorl -4(%%edi),%%eax\n\t"
167                 "subl $4,%%edi\n\t"
168                 "bsfl %%eax,%%edx\n"
169                 "1:\tsubl %%ebx,%%edi\n\t"
170                 "shll $3,%%edi\n\t"
171                 "addl %%edi,%%edx"
172                 :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
173                 :"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
174         return res;
175 }
176 
177 static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
178 {
179         unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
180         int set = 0, bit = offset & 31, res;
181         
182         if (bit) {
183                 /*
184                  * Look for zero in first byte
185                  */
186                 __asm__("bsfl %1,%0\n\t"
187                         "jne 1f\n\t"
188                         "movl $32, %0\n"
189                         "1:"
190                         : "=r" (set)
191                         : "r" (~(*p >> bit)));
192                 if (set < (32 - bit))
193                         return set + offset;
194                 set = 32 - bit;
195                 p++;
196         }
197         /*
198          * No zero yet, search remaining full bytes for a zero
199          */
200         res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
201         return (offset + set + res);
202 }
203 
204 /*
205  * ffz = Find First Zero in word. Undefined if no zero exists,
206  * so code should check against ~0UL first..
207  */
208 static __inline__ unsigned long ffz(unsigned long word)
209 {
210         __asm__("bsfl %1,%0"
211                 :"=r" (word)
212                 :"r" (~word));
213         return word;
214 }
215 
216 #ifdef __KERNEL__
217 
218 /*
219  * ffs: find first bit set. This is defined the same way as
220  * the libc and compiler builtin ffs routines, therefore
221  * differs in spirit from the above ffz (man ffs).
222  */
223 
224 static __inline__ int ffs(int x)
225 {
226         int r;
227 
228         __asm__("bsfl %1,%0\n\t"
229                 "jnz 1f\n\t"
230                 "movl $-1,%0\n"
231                 "1:" : "=r" (r) : "g" (x));
232         return r+1;
233 }
234 
235 /*
236  * hweightN: returns the hamming weight (i.e. the number
237  * of bits set) of a N-bit word
238  */
239 
240 #define hweight32(x) generic_hweight32(x)
241 #define hweight16(x) generic_hweight16(x)
242 #define hweight8(x) generic_hweight8(x)
243 
244 #endif /* __KERNEL__ */
245 
246 #ifdef __KERNEL__
247 
248 #define ext2_set_bit                 __test_and_set_bit
249 #define ext2_clear_bit               __test_and_clear_bit
250 #define ext2_test_bit                test_bit
251 #define ext2_find_first_zero_bit     find_first_zero_bit
252 #define ext2_find_next_zero_bit      find_next_zero_bit
253 
254 /* Bitmap functions for the minix filesystem.  */
255 #define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
256 #define minix_set_bit(nr,addr) __set_bit(nr,addr)
257 #define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
258 #define minix_test_bit(nr,addr) test_bit(nr,addr)
259 #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
260 
261 #endif /* __KERNEL__ */
262 
263 #endif /* _I386_BITOPS_H */
264 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.