linux-bk/include/asm-parisc/bitops.h
<<
>>
Prefs
   1#ifndef _PARISC_BITOPS_H
   2#define _PARISC_BITOPS_H
   3
   4#include <linux/compiler.h>
   5#include <asm/system.h>
   6#include <asm/byteorder.h>
   7#include <asm/atomic.h>
   8
   9/*
  10 * HP-PARISC specific bit operations
  11 * for a detailed description of the functions please refer
  12 * to include/asm-i386/bitops.h or kerneldoc
  13 */
  14
  15#ifdef __LP64__
  16#   define SHIFT_PER_LONG 6
  17#ifndef BITS_PER_LONG
  18#   define BITS_PER_LONG 64
  19#endif
  20#else
  21#   define SHIFT_PER_LONG 5
  22#ifndef BITS_PER_LONG
  23#   define BITS_PER_LONG 32
  24#endif
  25#endif
  26
  27#define CHOP_SHIFTCOUNT(x) ((x) & (BITS_PER_LONG - 1))
  28
  29
  30#define smp_mb__before_clear_bit()      smp_mb()
  31#define smp_mb__after_clear_bit()       smp_mb()
  32
  33static __inline__ void set_bit(int nr, void * address)
  34{
  35        unsigned long mask;
  36        unsigned long *addr = (unsigned long *) address;
  37        unsigned long flags;
  38
  39        addr += (nr >> SHIFT_PER_LONG);
  40        mask = 1L << CHOP_SHIFTCOUNT(nr);
  41        SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
  42        *addr |= mask;
  43        SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
  44}
  45
  46static __inline__ void __set_bit(int nr, void * address)
  47{
  48        unsigned long mask;
  49        unsigned long *addr = (unsigned long *) address;
  50
  51        addr += (nr >> SHIFT_PER_LONG);
  52        mask = 1L << CHOP_SHIFTCOUNT(nr);
  53        *addr |= mask;
  54}
  55
  56static __inline__ void clear_bit(int nr, void * address)
  57{
  58        unsigned long mask;
  59        unsigned long *addr = (unsigned long *) address;
  60        unsigned long flags;
  61
  62        addr += (nr >> SHIFT_PER_LONG);
  63        mask = 1L << CHOP_SHIFTCOUNT(nr);
  64        SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
  65        *addr &= ~mask;
  66        SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
  67}
  68
  69static __inline__ void __clear_bit(unsigned long nr, volatile void * address)
  70{
  71        unsigned long mask;
  72        unsigned long *addr = (unsigned long *) address;
  73
  74        addr += (nr >> SHIFT_PER_LONG);
  75        mask = 1L << CHOP_SHIFTCOUNT(nr);
  76        *addr &= ~mask;
  77}
  78
  79static __inline__ void change_bit(int nr, void * address)
  80{
  81        unsigned long mask;
  82        unsigned long *addr = (unsigned long *) address;
  83        unsigned long flags;
  84
  85        addr += (nr >> SHIFT_PER_LONG);
  86        mask = 1L << CHOP_SHIFTCOUNT(nr);
  87        SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
  88        *addr ^= mask;
  89        SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
  90}
  91
  92static __inline__ void __change_bit(int nr, void * address)
  93{
  94        unsigned long mask;
  95        unsigned long *addr = (unsigned long *) address;
  96
  97        addr += (nr >> SHIFT_PER_LONG);
  98        mask = 1L << CHOP_SHIFTCOUNT(nr);
  99        *addr ^= mask;
 100}
 101
 102static __inline__ int test_and_set_bit(int nr, void * address)
 103{
 104        unsigned long mask;
 105        unsigned long *addr = (unsigned long *) address;
 106        int oldbit;
 107        unsigned long flags;
 108
 109        addr += (nr >> SHIFT_PER_LONG);
 110        mask = 1L << CHOP_SHIFTCOUNT(nr);
 111        SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
 112        oldbit = (*addr & mask) ? 1 : 0;
 113        *addr |= mask;
 114        SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
 115
 116        return oldbit;
 117}
 118
 119static __inline__ int __test_and_set_bit(int nr, void * address)
 120{
 121        unsigned long mask;
 122        unsigned long *addr = (unsigned long *) address;
 123        int oldbit;
 124
 125        addr += (nr >> SHIFT_PER_LONG);
 126        mask = 1L << CHOP_SHIFTCOUNT(nr);
 127        oldbit = (*addr & mask) ? 1 : 0;
 128        *addr |= mask;
 129
 130        return oldbit;
 131}
 132
 133static __inline__ int test_and_clear_bit(int nr, void * address)
 134{
 135        unsigned long mask;
 136        unsigned long *addr = (unsigned long *) address;
 137        int oldbit;
 138        unsigned long flags;
 139
 140        addr += (nr >> SHIFT_PER_LONG);
 141        mask = 1L << CHOP_SHIFTCOUNT(nr);
 142        SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
 143        oldbit = (*addr & mask) ? 1 : 0;
 144        *addr &= ~mask;
 145        SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
 146
 147        return oldbit;
 148}
 149
 150static __inline__ int __test_and_clear_bit(int nr, void * address)
 151{
 152        unsigned long mask;
 153        unsigned long *addr = (unsigned long *) address;
 154        int oldbit;
 155
 156        addr += (nr >> SHIFT_PER_LONG);
 157        mask = 1L << CHOP_SHIFTCOUNT(nr);
 158        oldbit = (*addr & mask) ? 1 : 0;
 159        *addr &= ~mask;
 160
 161        return oldbit;
 162}
 163
 164static __inline__ int test_and_change_bit(int nr, void * address)
 165{
 166        unsigned long mask;
 167        unsigned long *addr = (unsigned long *) address;
 168        int oldbit;
 169        unsigned long flags;
 170
 171        addr += (nr >> SHIFT_PER_LONG);
 172        mask = 1L << CHOP_SHIFTCOUNT(nr);
 173        SPIN_LOCK_IRQSAVE(ATOMIC_HASH(addr), flags);
 174        oldbit = (*addr & mask) ? 1 : 0;
 175        *addr ^= mask;
 176        SPIN_UNLOCK_IRQRESTORE(ATOMIC_HASH(addr), flags);
 177
 178        return oldbit;
 179}
 180
 181static __inline__ int __test_and_change_bit(int nr, void * address)
 182{
 183        unsigned long mask;
 184        unsigned long *addr = (unsigned long *) address;
 185        int oldbit;
 186
 187        addr += (nr >> SHIFT_PER_LONG);
 188        mask = 1L << CHOP_SHIFTCOUNT(nr);
 189        oldbit = (*addr & mask) ? 1 : 0;
 190        *addr ^= mask;
 191
 192        return oldbit;
 193}
 194
 195static __inline__ int test_bit(int nr, const void *address)
 196{
 197        unsigned long mask;
 198        unsigned long *addr = (unsigned long *) address;
 199        
 200        addr += (nr >> SHIFT_PER_LONG);
 201        mask = 1L << CHOP_SHIFTCOUNT(nr);
 202        
 203        return !!(*addr & mask);
 204}
 205
 206extern __inline__ unsigned long ffz(unsigned long word)
 207{
 208        unsigned long result;
 209
 210        result = 0;
 211        while (word & 1) {
 212                result++;
 213                word >>= 1;
 214        }
 215
 216        return result;
 217}
 218
 219#ifdef __KERNEL__
 220
 221/**
 222 * __ffs - find first bit in word.
 223 * @word: The word to search
 224 *
 225 * Undefined if no bit exists, so code should check against 0 first.
 226 */
 227static __inline__ unsigned long __ffs(unsigned long word)
 228{
 229        unsigned long result = 0;
 230
 231        while (!(word & 1UL)) {
 232                result++;
 233                word >>= 1;
 234        }
 235        return result;
 236}
 237
 238/*
 239 * ffs: find first bit set. This is defined the same way as
 240 * the libc and compiler builtin ffs routines, therefore
 241 * differs in spirit from the above ffz (man ffs).
 242 */
 243static __inline__ int ffs(int x)
 244{
 245        if (!x)
 246                return 0;
 247        return __ffs((unsigned long)x);
 248}
 249
 250/*
 251 * fls: find last bit set.
 252 */
 253
 254#define fls(x) generic_fls(x)
 255
 256/*
 257 * hweightN: returns the hamming weight (i.e. the number
 258 * of bits set) of a N-bit word
 259 */
 260
 261#define hweight32(x) generic_hweight32(x)
 262#define hweight16(x) generic_hweight16(x)
 263#define hweight8(x) generic_hweight8(x)
 264
 265/*
 266 * Every architecture must define this function. It's the fastest
 267 * way of searching a 140-bit bitmap where the first 100 bits are
 268 * unlikely to be set. It's guaranteed that at least one of the 140
 269 * bits is cleared.
 270 */
 271static inline int sched_find_first_bit(unsigned long *b)
 272{
 273#ifndef __LP64__
 274        if (unlikely(b[0]))
 275                return __ffs(b[0]);
 276        if (unlikely(b[1]))
 277                return __ffs(b[1]) + 32;
 278        if (unlikely(b[2]))
 279                return __ffs(b[2]) + 64;
 280        if (b[3])
 281                return __ffs(b[3]) + 96;
 282        return __ffs(b[4]) + 128;
 283#else
 284        if (unlikely(b[0]))
 285                return __ffs(b[0]);
 286        if (unlikely(((unsigned int)b[1])))
 287                return __ffs(b[1]) + 64;
 288        if (b[1] >> 32)
 289                return __ffs(b[1] >> 32) + 96;
 290        return __ffs(b[2]) + 128;
 291#endif
 292}
 293
 294#endif /* __KERNEL__ */
 295
 296/*
 297 * This implementation of find_{first,next}_zero_bit was stolen from
 298 * Linus' asm-alpha/bitops.h.
 299 */
 300#define find_first_zero_bit(addr, size) \
 301        find_next_zero_bit((addr), (size), 0)
 302
 303static __inline__ unsigned long find_next_zero_bit(void * addr, unsigned long size, unsigned long offset)
 304{
 305        unsigned long * p = ((unsigned long *) addr) + (offset >> SHIFT_PER_LONG);
 306        unsigned long result = offset & ~(BITS_PER_LONG-1);
 307        unsigned long tmp;
 308
 309        if (offset >= size)
 310                return size;
 311        size -= result;
 312        offset &= (BITS_PER_LONG-1);
 313        if (offset) {
 314                tmp = *(p++);
 315                tmp |= ~0UL >> (BITS_PER_LONG-offset);
 316                if (size < BITS_PER_LONG)
 317                        goto found_first;
 318                if (~tmp)
 319                        goto found_middle;
 320                size -= BITS_PER_LONG;
 321                result += BITS_PER_LONG;
 322        }
 323        while (size & ~(BITS_PER_LONG -1)) {
 324                if (~(tmp = *(p++)))
 325                        goto found_middle;
 326                result += BITS_PER_LONG;
 327                size -= BITS_PER_LONG;
 328        }
 329        if (!size)
 330                return result;
 331        tmp = *p;
 332found_first:
 333        tmp |= ~0UL << size;
 334found_middle:
 335        return result + ffz(tmp);
 336}
 337
 338static __inline__ unsigned long find_next_bit(unsigned long *addr, unsigned long size, unsigned long offset)
 339{
 340        unsigned long *p = addr + (offset >> 6);
 341        unsigned long result = offset & ~(BITS_PER_LONG-1);
 342        unsigned long tmp;
 343
 344        if (offset >= size)
 345                return size;
 346        size -= result;
 347        offset &= (BITS_PER_LONG-1);
 348        if (offset) {
 349                tmp = *(p++);
 350                tmp &= (~0UL << offset);
 351                if (size < BITS_PER_LONG)
 352                        goto found_first;
 353                if (tmp)
 354                        goto found_middle;
 355                size -= BITS_PER_LONG;
 356                result += BITS_PER_LONG;
 357        }
 358        while (size & ~(BITS_PER_LONG-1)) {
 359                if ((tmp = *(p++)))
 360                        goto found_middle;
 361                result += BITS_PER_LONG;
 362                size -= BITS_PER_LONG;
 363        }
 364        if (!size)
 365                return result;
 366        tmp = *p;
 367
 368found_first:
 369        tmp &= (~0UL >> (BITS_PER_LONG - size));
 370        if (tmp == 0UL)        /* Are any bits set? */
 371                return result + size; /* Nope. */
 372found_middle:
 373        return result + __ffs(tmp);
 374}
 375
 376#define _EXT2_HAVE_ASM_BITOPS_
 377
 378#ifdef __KERNEL__
 379/*
 380 * test_and_{set,clear}_bit guarantee atomicity without
 381 * disabling interrupts.
 382 */
 383#ifdef __LP64__
 384#define ext2_set_bit(nr, addr)          test_and_set_bit((nr) ^ 0x38, addr)
 385#define ext2_clear_bit(nr, addr)        test_and_clear_bit((nr) ^ 0x38, addr)
 386#else
 387#define ext2_set_bit(nr, addr)          test_and_set_bit((nr) ^ 0x18, addr)
 388#define ext2_clear_bit(nr, addr)        test_and_clear_bit((nr) ^ 0x18, addr)
 389#endif
 390
 391#endif  /* __KERNEL__ */
 392
 393static __inline__ int ext2_test_bit(int nr, __const__ void * addr)
 394{
 395        __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
 396
 397        return (ADDR[nr >> 3] >> (nr & 7)) & 1;
 398}
 399
 400/*
 401 * This implementation of ext2_find_{first,next}_zero_bit was stolen from
 402 * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
 403 */
 404
 405#define ext2_find_first_zero_bit(addr, size) \
 406        ext2_find_next_zero_bit((addr), (size), 0)
 407
 408extern __inline__ unsigned long ext2_find_next_zero_bit(void *addr,
 409        unsigned long size, unsigned long offset)
 410{
 411        unsigned int *p = ((unsigned int *) addr) + (offset >> 5);
 412        unsigned int result = offset & ~31UL;
 413        unsigned int tmp;
 414
 415        if (offset >= size)
 416                return size;
 417        size -= result;
 418        offset &= 31UL;
 419        if (offset) {
 420                tmp = cpu_to_le32p(p++);
 421                tmp |= ~0UL >> (32-offset);
 422                if (size < 32)
 423                        goto found_first;
 424                if (tmp != ~0U)
 425                        goto found_middle;
 426                size -= 32;
 427                result += 32;
 428        }
 429        while (size >= 32) {
 430                if ((tmp = cpu_to_le32p(p++)) != ~0U)
 431                        goto found_middle;
 432                result += 32;
 433                size -= 32;
 434        }
 435        if (!size)
 436                return result;
 437        tmp = cpu_to_le32p(p);
 438found_first:
 439        tmp |= ~0U << size;
 440found_middle:
 441        return result + ffz(tmp);
 442}
 443
 444/* Bitmap functions for the minix filesystem.  */
 445#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
 446#define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
 447#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
 448#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
 449#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
 450
 451#endif /* _PARISC_BITOPS_H */
 452
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.