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

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

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

  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 

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