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

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

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

  1 #ifndef _ASM_IA64_BITOPS_H
  2 #define _ASM_IA64_BITOPS_H
  3 
  4 /*
  5  * Copyright (C) 1998-2000 Hewlett-Packard Co
  6  * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com>
  7  *
  8  * 02/04/00 D. Mosberger  Require 64-bit alignment for bitops, per suggestion from davem
  9  */
 10 
 11 #include <asm/system.h>
 12 
 13 /*
 14  * These operations need to be atomic.  The address must be (at least)
 15  * 32-bit aligned.  Note that there are driver (e.g., eepro100) which
 16  * use these operations to operate on hw-defined data-structures, so
 17  * we can't easily change these operations to force a bigger
 18  * alignment.
 19  *
 20  * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
 21  */
 22 
 23 static __inline__ void
 24 set_bit (int nr, volatile void *addr)
 25 {
 26         __u32 bit, old, new;
 27         volatile __u32 *m;
 28         CMPXCHG_BUGCHECK_DECL
 29 
 30         m = (volatile __u32 *) addr + (nr >> 5);
 31         bit = 1 << (nr & 31);
 32         do {
 33                 CMPXCHG_BUGCHECK(m);
 34                 old = *m;
 35                 new = old | bit;
 36         } while (cmpxchg_acq(m, old, new) != old);
 37 }
 38 
 39 /*
 40  * clear_bit() doesn't provide any barrier for the compiler.
 41  */
 42 #define smp_mb__before_clear_bit()      smp_mb()
 43 #define smp_mb__after_clear_bit()       smp_mb()
 44 static __inline__ void
 45 clear_bit (int nr, volatile void *addr)
 46 {
 47         __u32 mask, old, new;
 48         volatile __u32 *m;
 49         CMPXCHG_BUGCHECK_DECL
 50 
 51         m = (volatile __u32 *) addr + (nr >> 5);
 52         mask = ~(1 << (nr & 31));
 53         do {
 54                 CMPXCHG_BUGCHECK(m);
 55                 old = *m;
 56                 new = old & mask;
 57         } while (cmpxchg_acq(m, old, new) != old);
 58 }
 59 
 60 static __inline__ void
 61 change_bit (int nr, volatile void *addr)
 62 {
 63         __u32 bit, old, new;
 64         volatile __u32 *m;
 65         CMPXCHG_BUGCHECK_DECL
 66 
 67         m = (volatile __u32 *) addr + (nr >> 5);
 68         bit = (1 << (nr & 31));
 69         do {
 70                 CMPXCHG_BUGCHECK(m);
 71                 old = *m;
 72                 new = old ^ bit;
 73         } while (cmpxchg_acq(m, old, new) != old);
 74 }
 75 
 76 static __inline__ int
 77 test_and_set_bit (int nr, volatile void *addr)
 78 {
 79         __u32 bit, old, new;
 80         volatile __u32 *m;
 81         CMPXCHG_BUGCHECK_DECL
 82 
 83         m = (volatile __u32 *) addr + (nr >> 5);
 84         bit = 1 << (nr & 31);
 85         do {
 86                 CMPXCHG_BUGCHECK(m);
 87                 old = *m;
 88                 new = old | bit;
 89         } while (cmpxchg_acq(m, old, new) != old);
 90         return (old & bit) != 0;
 91 }
 92 
 93 static __inline__ int
 94 test_and_clear_bit (int nr, volatile void *addr)
 95 {
 96         __u32 mask, old, new;
 97         volatile __u32 *m;
 98         CMPXCHG_BUGCHECK_DECL
 99 
100         m = (volatile __u32 *) addr + (nr >> 5);
101         mask = ~(1 << (nr & 31));
102         do {
103                 CMPXCHG_BUGCHECK(m);
104                 old = *m;
105                 new = old & mask;
106         } while (cmpxchg_acq(m, old, new) != old);
107         return (old & ~mask) != 0;
108 }
109 
110 static __inline__ int
111 test_and_change_bit (int nr, volatile void *addr)
112 {
113         __u32 bit, old, new;
114         volatile __u32 *m;
115         CMPXCHG_BUGCHECK_DECL
116 
117         m = (volatile __u32 *) addr + (nr >> 5);
118         bit = (1 << (nr & 31));
119         do {
120                 CMPXCHG_BUGCHECK(m);
121                 old = *m;
122                 new = old ^ bit;
123         } while (cmpxchg_acq(m, old, new) != old);
124         return (old & bit) != 0;
125 }
126 
127 static __inline__ int
128 test_bit (int nr, volatile void *addr)
129 {
130         return 1 & (((const volatile __u32 *) addr)[nr >> 5] >> (nr & 31));
131 }
132 
133 /*
134  * ffz = Find First Zero in word. Undefined if no zero exists,
135  * so code should check against ~0UL first..
136  */
137 static inline unsigned long
138 ffz (unsigned long x)
139 {
140         unsigned long result;
141 
142         __asm__ ("popcnt %0=%1" : "=r" (result) : "r" (x & (~x - 1)));
143         return result;
144 }
145 
146 #ifdef __KERNEL__
147 
148 /*
149  * Find the most significant bit that is set (undefined if no bit is
150  * set).
151  */
152 static inline unsigned long
153 ia64_fls (unsigned long x)
154 {
155         double d = x;
156         long exp;
157 
158         __asm__ ("getf.exp %0=%1" : "=r"(exp) : "f"(d));
159         return exp - 0xffff;
160 }
161 /*
162  * ffs: find first bit set. This is defined the same way as
163  * the libc and compiler builtin ffs routines, therefore
164  * differs in spirit from the above ffz (man ffs).
165  */
166 #define ffs(x)  __builtin_ffs(x)
167 
168 /*
169  * hweightN: returns the hamming weight (i.e. the number
170  * of bits set) of a N-bit word
171  */
172 static __inline__ unsigned long
173 hweight64 (unsigned long x)
174 {
175         unsigned long result;
176         __asm__ ("popcnt %0=%1" : "=r" (result) : "r" (x));
177         return result;
178 }
179 
180 #define hweight32(x) hweight64 ((x) & 0xfffffffful)
181 #define hweight16(x) hweight64 ((x) & 0xfffful)
182 #define hweight8(x)  hweight64 ((x) & 0xfful)
183 
184 #endif /* __KERNEL__ */
185 
186 /*
187  * Find next zero bit in a bitmap reasonably efficiently..
188  */
189 static inline int
190 find_next_zero_bit (void *addr, unsigned long size, unsigned long offset)
191 {
192         unsigned long *p = ((unsigned long *) addr) + (offset >> 6);
193         unsigned long result = offset & ~63UL;
194         unsigned long tmp;
195 
196         if (offset >= size)
197                 return size;
198         size -= result;
199         offset &= 63UL;
200         if (offset) {
201                 tmp = *(p++);
202                 tmp |= ~0UL >> (64-offset);
203                 if (size < 64)
204                         goto found_first;
205                 if (~tmp)
206                         goto found_middle;
207                 size -= 64;
208                 result += 64;
209         }
210         while (size & ~63UL) {
211                 if (~(tmp = *(p++)))
212                         goto found_middle;
213                 result += 64;
214                 size -= 64;
215         }
216         if (!size)
217                 return result;
218         tmp = *p;
219 found_first:
220         tmp |= ~0UL << size;
221 found_middle:
222         return result + ffz(tmp);
223 }
224 
225 /*
226  * The optimizer actually does good code for this case..
227  */
228 #define find_first_zero_bit(addr, size) find_next_zero_bit((addr), (size), 0)
229 
230 #ifdef __KERNEL__
231 
232 #define ext2_set_bit                 test_and_set_bit
233 #define ext2_clear_bit               test_and_clear_bit
234 #define ext2_test_bit                test_bit
235 #define ext2_find_first_zero_bit     find_first_zero_bit
236 #define ext2_find_next_zero_bit      find_next_zero_bit
237 
238 /* Bitmap functions for the minix filesystem.  */
239 #define minix_test_and_set_bit(nr,addr)         test_and_set_bit(nr,addr)
240 #define minix_set_bit(nr,addr)                  set_bit(nr,addr)
241 #define minix_test_and_clear_bit(nr,addr)       test_and_clear_bit(nr,addr)
242 #define minix_test_bit(nr,addr)                 test_bit(nr,addr)
243 #define minix_find_first_zero_bit(addr,size)    find_first_zero_bit(addr,size)
244 
245 #endif /* __KERNEL__ */
246 
247 #endif /* _ASM_IA64_BITOPS_H */
248 

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