| #include <linux/bitops.h> |
| #include <linux/module.h> |
| |
| /** |
| * find_next_bit - find the first set bit in a memory region |
| * @addr: The address to base the search on |
| * @offset: The bitnumber to start searching at |
| * @size: The maximum size to search |
| */ |
| int find_next_bit(const unsigned long *addr, int size, int offset) |
| { |
| const unsigned long *p = addr + (offset >> 5); |
| int set = 0, bit = offset & 31, res; |
| |
| if (bit) { |
| /* |
| * Look for nonzero in the first 32 bits: |
| */ |
| __asm__("bsfl %1,%0\n\t" |
| "jne 1f\n\t" |
| "movl $32, %0\n" |
| "1:" |
| : "=r" (set) |
| : "r" (*p >> bit)); |
| if (set < (32 - bit)) |
| return set + offset; |
| set = 32 - bit; |
| p++; |
| } |
| /* |
| * No set bit yet, search remaining full words for a bit |
| */ |
| res = find_first_bit (p, size - 32 * (p - addr)); |
| return (offset + set + res); |
| } |
| EXPORT_SYMBOL(find_next_bit); |
| |
| /** |
| * find_next_zero_bit - find the first zero bit in a memory region |
| * @addr: The address to base the search on |
| * @offset: The bitnumber to start searching at |
| * @size: The maximum size to search |
| */ |
| int find_next_zero_bit(const unsigned long *addr, int size, int offset) |
| { |
| const unsigned long *p = addr + (offset >> 5); |
| int set = 0, bit = offset & 31, res; |
| |
| if (bit) { |
| /* |
| * Look for zero in the first 32 bits. |
| */ |
| __asm__("bsfl %1,%0\n\t" |
| "jne 1f\n\t" |
| "movl $32, %0\n" |
| "1:" |
| : "=r" (set) |
| : "r" (~(*p >> bit))); |
| if (set < (32 - bit)) |
| return set + offset; |
| set = 32 - bit; |
| p++; |
| } |
| /* |
| * No zero yet, search remaining full bytes for a zero |
| */ |
| res = find_first_zero_bit(p, size - 32 * (p - addr)); |
| return (offset + set + res); |
| } |
| EXPORT_SYMBOL(find_next_zero_bit); |