71 lines
1.6 KiB
C
71 lines
1.6 KiB
C
|
#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);
|