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

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

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

  1 #ifndef __ASM_SH_BITOPS_H
  2 #define __ASM_SH_BITOPS_H
  3 
  4 #ifdef __KERNEL__
  5 #include <asm/system.h>
  6 /* For __swab32 */
  7 #include <asm/byteorder.h>
  8 
  9 static __inline__ void set_bit(int nr, volatile void * addr)
 10 {
 11         int     mask;
 12         volatile unsigned int *a = addr;
 13         unsigned long flags;
 14 
 15         a += nr >> 5;
 16         mask = 1 << (nr & 0x1f);
 17         save_and_cli(flags);
 18         *a |= mask;
 19         restore_flags(flags);
 20 }
 21 
 22 /*
 23  * clear_bit() doesn't provide any barrier for the compiler.
 24  */
 25 #define smp_mb__before_clear_bit()      barrier()
 26 #define smp_mb__after_clear_bit()       barrier()
 27 static __inline__ void clear_bit(int nr, volatile void * addr)
 28 {
 29         int     mask;
 30         volatile unsigned int *a = addr;
 31         unsigned long flags;
 32 
 33         a += nr >> 5;
 34         mask = 1 << (nr & 0x1f);
 35         save_and_cli(flags);
 36         *a &= ~mask;
 37         restore_flags(flags);
 38 }
 39 
 40 static __inline__ void change_bit(int nr, volatile void * addr)
 41 {
 42         int     mask;
 43         volatile unsigned int *a = addr;
 44         unsigned long flags;
 45 
 46         a += nr >> 5;
 47         mask = 1 << (nr & 0x1f);
 48         save_and_cli(flags);
 49         *a ^= mask;
 50         restore_flags(flags);
 51 }
 52 
 53 static __inline__ int test_and_set_bit(int nr, volatile void * addr)
 54 {
 55         int     mask, retval;
 56         volatile unsigned int *a = addr;
 57         unsigned long flags;
 58 
 59         a += nr >> 5;
 60         mask = 1 << (nr & 0x1f);
 61         save_and_cli(flags);
 62         retval = (mask & *a) != 0;
 63         *a |= mask;
 64         restore_flags(flags);
 65 
 66         return retval;
 67 }
 68 
 69 static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
 70 {
 71         int     mask, retval;
 72         volatile unsigned int *a = addr;
 73         unsigned long flags;
 74 
 75         a += nr >> 5;
 76         mask = 1 << (nr & 0x1f);
 77         save_and_cli(flags);
 78         retval = (mask & *a) != 0;
 79         *a &= ~mask;
 80         restore_flags(flags);
 81 
 82         return retval;
 83 }
 84 
 85 static __inline__ int test_and_change_bit(int nr, volatile void * addr)
 86 {
 87         int     mask, retval;
 88         volatile unsigned int *a = addr;
 89         unsigned long flags;
 90 
 91         a += nr >> 5;
 92         mask = 1 << (nr & 0x1f);
 93         save_and_cli(flags);
 94         retval = (mask & *a) != 0;
 95         *a ^= mask;
 96         restore_flags(flags);
 97 
 98         return retval;
 99 }
100 
101 
102 static __inline__ int test_bit(int nr, const volatile void *addr)
103 {
104         return 1UL & (((const volatile unsigned int *) addr)[nr >> 5] >> (nr & 31));
105 }
106 
107 static __inline__ unsigned long ffz(unsigned long word)
108 {
109         unsigned long result;
110 
111         __asm__("1:\n\t"
112                 "shlr   %1\n\t"
113                 "bt/s   1b\n\t"
114                 " add   #1, %0"
115                 : "=r" (result), "=r" (word)
116                 : "" (~0L), "1" (word)
117                 : "t");
118         return result;
119 }
120 
121 static __inline__ int find_next_zero_bit(void *addr, int size, int offset)
122 {
123         unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
124         unsigned long result = offset & ~31UL;
125         unsigned long tmp;
126 
127         if (offset >= size)
128                 return size;
129         size -= result;
130         offset &= 31UL;
131         if (offset) {
132                 tmp = *(p++);
133                 tmp |= ~0UL >> (32-offset);
134                 if (size < 32)
135                         goto found_first;
136                 if (~tmp)
137                         goto found_middle;
138                 size -= 32;
139                 result += 32;
140         }
141         while (size & ~31UL) {
142                 if (~(tmp = *(p++)))
143                         goto found_middle;
144                 result += 32;
145                 size -= 32;
146         }
147         if (!size)
148                 return result;
149         tmp = *p;
150 
151 found_first:
152         tmp |= ~0UL << size;
153 found_middle:
154         return result + ffz(tmp);
155 }
156 
157 #define find_first_zero_bit(addr, size) \
158         find_next_zero_bit((addr), (size), 0)
159 
160 #ifdef __LITTLE_ENDIAN__
161 #define ext2_set_bit(nr, addr) test_and_set_bit((nr), (addr))
162 #define ext2_clear_bit(nr, addr) test_and_clear_bit((nr), (addr))
163 #define ext2_test_bit(nr, addr) test_bit((nr), (addr))
164 #define ext2_find_first_zero_bit(addr, size) find_first_zero_bit((addr), (size))
165 #define ext2_find_next_zero_bit(addr, size, offset) \
166                 find_next_zero_bit((addr), (size), (offset))
167 #else
168 static __inline__ int ext2_set_bit(int nr, volatile void * addr)
169 {
170         int             mask, retval;
171         unsigned long   flags;
172         volatile unsigned char  *ADDR = (unsigned char *) addr;
173 
174         ADDR += nr >> 3;
175         mask = 1 << (nr & 0x07);
176         save_and_cli(flags);
177         retval = (mask & *ADDR) != 0;
178         *ADDR |= mask;
179         restore_flags(flags);
180         return retval;
181 }
182 
183 static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
184 {
185         int             mask, retval;
186         unsigned long   flags;
187         volatile unsigned char  *ADDR = (unsigned char *) addr;
188 
189         ADDR += nr >> 3;
190         mask = 1 << (nr & 0x07);
191         save_and_cli(flags);
192         retval = (mask & *ADDR) != 0;
193         *ADDR &= ~mask;
194         restore_flags(flags);
195         return retval;
196 }
197 
198 static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
199 {
200         int                     mask;
201         const volatile unsigned char    *ADDR = (const unsigned char *) addr;
202 
203         ADDR += nr >> 3;
204         mask = 1 << (nr & 0x07);
205         return ((mask & *ADDR) != 0);
206 }
207 
208 #define ext2_find_first_zero_bit(addr, size) \
209         ext2_find_next_zero_bit((addr), (size), 0)
210 
211 static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
212 {
213         unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
214         unsigned long result = offset & ~31UL;
215         unsigned long tmp;
216 
217         if (offset >= size)
218                 return size;
219         size -= result;
220         offset &= 31UL;
221         if(offset) {
222                 /* We hold the little endian value in tmp, but then the
223                  * shift is illegal. So we could keep a big endian value
224                  * in tmp, like this:
225                  *
226                  * tmp = __swab32(*(p++));
227                  * tmp |= ~0UL >> (32-offset);
228                  *
229                  * but this would decrease preformance, so we change the
230                  * shift:
231                  */
232                 tmp = *(p++);
233                 tmp |= __swab32(~0UL >> (32-offset));
234                 if(size < 32)
235                         goto found_first;
236                 if(~tmp)
237                         goto found_middle;
238                 size -= 32;
239                 result += 32;
240         }
241         while(size & ~31UL) {
242                 if(~(tmp = *(p++)))
243                         goto found_middle;
244                 result += 32;
245                 size -= 32;
246         }
247         if(!size)
248                 return result;
249         tmp = *p;
250 
251 found_first:
252         /* tmp is little endian, so we would have to swab the shift,
253          * see above. But then we have to swab tmp below for ffz, so
254          * we might as well do this here.
255          */
256         return result + ffz(__swab32(tmp) | (~0UL << size));
257 found_middle:
258         return result + ffz(__swab32(tmp));
259 }
260 #endif
261 
262 /* Bitmap functions for the minix filesystem.  */
263 #define minix_test_and_set_bit(nr,addr) test_and_set_bit(nr,addr)
264 #define minix_set_bit(nr,addr) set_bit(nr,addr)
265 #define minix_test_and_clear_bit(nr,addr) test_and_clear_bit(nr,addr)
266 #define minix_test_bit(nr,addr) test_bit(nr,addr)
267 #define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
268 
269 #endif /* __KERNEL__ */
270 
271 #endif /* __ASM_SH_BITOPS_H */
272 

~ [ 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.