|  | /* find_next_bit.c: fallback find next bit implementation | 
|  | * | 
|  | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 
|  | * Written by David Howells (dhowells@redhat.com) | 
|  | * | 
|  | * This program is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU General Public License | 
|  | * as published by the Free Software Foundation; either version | 
|  | * 2 of the License, or (at your option) any later version. | 
|  | */ | 
|  |  | 
|  | #include <arch/arch.h> | 
|  | #include <error.h> | 
|  | #include <atomic.h> | 
|  | #include <string.h> | 
|  | #include <assert.h> | 
|  | #include <bitops.h> | 
|  | #include <bitmap.h> | 
|  |  | 
|  | #define BITOP_WORD(nr)		((nr) / BITS_PER_LONG) | 
|  |  | 
|  | /* | 
|  | * Find the next set bit in a memory region. | 
|  | */ | 
|  | unsigned long find_next_bit(const unsigned long *addr, unsigned long size, | 
|  | unsigned long offset) | 
|  | { | 
|  | const unsigned long *p = addr + BITOP_WORD(offset); | 
|  | unsigned long result = offset & ~(BITS_PER_LONG-1); | 
|  | unsigned long tmp; | 
|  |  | 
|  | if (offset >= size) | 
|  | return size; | 
|  | size -= result; | 
|  | offset %= BITS_PER_LONG; | 
|  | if (offset) { | 
|  | tmp = *(p++); | 
|  | tmp &= (~0UL << offset); | 
|  | if (size < BITS_PER_LONG) | 
|  | goto found_first; | 
|  | if (tmp) | 
|  | goto found_middle; | 
|  | size -= BITS_PER_LONG; | 
|  | result += BITS_PER_LONG; | 
|  | } | 
|  | while (size & ~(BITS_PER_LONG-1)) { | 
|  | if ((tmp = *(p++))) | 
|  | goto found_middle; | 
|  | result += BITS_PER_LONG; | 
|  | size -= BITS_PER_LONG; | 
|  | } | 
|  | if (!size) | 
|  | return result; | 
|  | tmp = *p; | 
|  |  | 
|  | found_first: | 
|  | tmp &= (~0UL >> (BITS_PER_LONG - size)); | 
|  | if (tmp == 0UL)		/* Are any bits set? */ | 
|  | return result + size;	/* Nope. */ | 
|  | found_middle: | 
|  | return result + __ffs(tmp); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * This implementation of find_{first,next}_zero_bit was stolen from | 
|  | * Linus' asm-alpha/bitops.h. | 
|  | */ | 
|  | unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, | 
|  | unsigned long offset) | 
|  | { | 
|  | const unsigned long *p = addr + BITOP_WORD(offset); | 
|  | unsigned long result = offset & ~(BITS_PER_LONG-1); | 
|  | unsigned long tmp; | 
|  |  | 
|  | if (offset >= size) | 
|  | return size; | 
|  | size -= result; | 
|  | offset %= BITS_PER_LONG; | 
|  | if (offset) { | 
|  | tmp = *(p++); | 
|  | tmp |= ~0UL >> (BITS_PER_LONG - offset); | 
|  | if (size < BITS_PER_LONG) | 
|  | goto found_first; | 
|  | if (~tmp) | 
|  | goto found_middle; | 
|  | size -= BITS_PER_LONG; | 
|  | result += BITS_PER_LONG; | 
|  | } | 
|  | while (size & ~(BITS_PER_LONG-1)) { | 
|  | if (~(tmp = *(p++))) | 
|  | goto found_middle; | 
|  | result += BITS_PER_LONG; | 
|  | size -= BITS_PER_LONG; | 
|  | } | 
|  | if (!size) | 
|  | return result; | 
|  | tmp = *p; | 
|  |  | 
|  | found_first: | 
|  | tmp |= ~0UL << size; | 
|  | if (tmp == ~0UL)	/* Are any bits zero? */ | 
|  | return result + size;	/* Nope. */ | 
|  | found_middle: | 
|  | return result + ffz(tmp); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Find the first set bit in a memory region. | 
|  | */ | 
|  | unsigned long find_first_bit(const unsigned long *addr, unsigned long size) | 
|  | { | 
|  | const unsigned long *p = addr; | 
|  | unsigned long result = 0; | 
|  | unsigned long tmp; | 
|  |  | 
|  | while (size & ~(BITS_PER_LONG-1)) { | 
|  | if ((tmp = *(p++))) | 
|  | goto found; | 
|  | result += BITS_PER_LONG; | 
|  | size -= BITS_PER_LONG; | 
|  | } | 
|  | if (!size) | 
|  | return result; | 
|  |  | 
|  | tmp = (*p) & (~0UL >> (BITS_PER_LONG - size)); | 
|  | if (tmp == 0UL)		/* Are any bits set? */ | 
|  | return result + size;	/* Nope. */ | 
|  | found: | 
|  | return result + __ffs(tmp); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Find the first cleared bit in a memory region. | 
|  | */ | 
|  | unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) | 
|  | { | 
|  | const unsigned long *p = addr; | 
|  | unsigned long result = 0; | 
|  | unsigned long tmp; | 
|  |  | 
|  | while (size & ~(BITS_PER_LONG-1)) { | 
|  | if (~(tmp = *(p++))) | 
|  | goto found; | 
|  | result += BITS_PER_LONG; | 
|  | size -= BITS_PER_LONG; | 
|  | } | 
|  | if (!size) | 
|  | return result; | 
|  |  | 
|  | tmp = (*p) | (~0UL << size); | 
|  | if (tmp == ~0UL)	/* Are any bits zero? */ | 
|  | return result + size;	/* Nope. */ | 
|  | found: | 
|  | return result + ffz(tmp); | 
|  | } | 
|  |  |