内核API没有通用的标准 即使在内核的文档和头文件也没详细给出
一个多平台开发中多处用到bitops 结果碰到许多问题
1
int find_first_zero_bit(void * addr, unsigned size);
int find_next_zero_bit(void * addr, int size, int offset);
找到0bit时,各平台都返回0~size-1
在x86下,没有找到0bit时,返回size
在arm下,没有找到0bit时,则返回size+1
所以通用的判断方法是,检查返回值是否>=size
2
test_bit
test_and_set_bit
test_and_clear_bit
0 bit 返回0是一定的
1 bit各个平台不一样 arm返回1 x86返回 ~0(全FF)
因此通用的检查方法是判断是0或者非0
3
2.6 引入了
find_first_bit
find_next_bit
用来查找1bit
内核头文件确实有了新的特性
但是在fc4的用户头文件中却没看到这个新特性,这个头文件在内核和用户空间不是应该一样么??
arm平台的uclinux中也没有,因此打算自己加上
它的实现在arch/armnommu/lib/findbits.S中
#include <linux/linkage.h>
#include <asm/assembler.h>
.text
/*
* Purpose : Find a 'zero' bit
* Prototype: int find_first_zero_bit(void *addr, int maxbit);
*/
ENTRY(find_first_zero_bit)
mov r2, #0
.bytelp: ldrb r3, [r0, r2, lsr #3]
eors r3, r3, #0xff @ invert bits
bne .found @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
cmp r2, r1 @ any more?
bcc .bytelp
add r0, r1, #1 @ no free bits
RETINSTR(mov,pc,lr)
/*
* Purpose : Find next 'zero' bit
* Prototype: int find_next_zero_bit(void *addr, int maxbit, int offset)
*/
ENTRY(find_next_zero_bit)
ands ip, r2, #7
beq .bytelp @ If new byte, goto old routine
ldrb r3, [r0, r2, lsr#3]
eor r3, r3, #0xff @ now looking for a 1 bit
movs r3, r3, lsr ip @ shift off unused bits
orreq r2, r2, #7 @ if zero, then no bits here
addeq r2, r2, #1 @ align bit pointer
beq .bytelp @ loop for next bit
/*
* One or more bits in the LSB of r3 are assumed to be set.
*/
.found: tst r3, #0x0f
addeq r2, r2, #4
movne r3, r3, lsl #4
tst r3, #0x30
addeq r2, r2, #2
movne r3, r3, lsl #2
tst r3, #0x40
addeq r2, r2, #1
mov r0, r2
RETINSTR(mov,pc,lr)
可以发现它的操作竟然是先将数字进行反转 即0->1 1->0后对1进行搜索
那简单的修改一下就应该能够搞定了
在代码后面加入下面代码
/*
* Purpose : Find a 'one' bit
* Prototype: int find_first_bit(void *addr, int maxbit);
*/
ENTRY(find_first_bit)
mov r2, #0
.bbytelp: ldrb r3, [r0, r2, lsr #3]
movs r3, r3 // 将xor改成movs 触发标志寄存器 保证下面的bne正确跳转
bne .bfound @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
cmp r2, r1 @ any more?
bcc .bbytelp
add r0, r1, #1 @ no free bits
RETINSTR(mov,pc,lr)
/*
* Purpose : Find next 'one' bit
* Prototype: int find_next_bit(void *addr, int maxbit, int offset)
*/
ENTRY(find_next_bit)
ands ip, r2, #7
beq .bbytelp @ If new byte, goto old routine
ldrb r3, [r0, r2, lsr#3]
movs r3, r3, lsr ip @ shift off unused bits
// 去掉了xor
orreq r2, r2, #7 @ if zero, then no bits here
addeq r2, r2, #1 @ align bit pointer
beq .bbytelp @ loop for next bit
/*
* One or more bits in the LSB of r3 are assumed to be set.
*/
.bfound: tst r3, #0x0f
addeq r2, r2, #4
movne r3, r3, lsl #4
tst r3, #0x30
addeq r2, r2, #2
movne r3, r3, lsl #2
tst r3, #0x40
addeq r2, r2, #1
mov r0, r2
RETINSTR(mov,pc,lr)
一个多平台开发中多处用到bitops 结果碰到许多问题
1
int find_first_zero_bit(void * addr, unsigned size);
int find_next_zero_bit(void * addr, int size, int offset);
找到0bit时,各平台都返回0~size-1
在x86下,没有找到0bit时,返回size
在arm下,没有找到0bit时,则返回size+1
所以通用的判断方法是,检查返回值是否>=size
2
test_bit
test_and_set_bit
test_and_clear_bit
0 bit 返回0是一定的
1 bit各个平台不一样 arm返回1 x86返回 ~0(全FF)
因此通用的检查方法是判断是0或者非0
3
2.6 引入了
find_first_bit
find_next_bit
用来查找1bit
内核头文件确实有了新的特性
但是在fc4的用户头文件中却没看到这个新特性,这个头文件在内核和用户空间不是应该一样么??
arm平台的uclinux中也没有,因此打算自己加上
它的实现在arch/armnommu/lib/findbits.S中
#include <linux/linkage.h>
#include <asm/assembler.h>
.text
/*
* Purpose : Find a 'zero' bit
* Prototype: int find_first_zero_bit(void *addr, int maxbit);
*/
ENTRY(find_first_zero_bit)
mov r2, #0
.bytelp: ldrb r3, [r0, r2, lsr #3]
eors r3, r3, #0xff @ invert bits
bne .found @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
cmp r2, r1 @ any more?
bcc .bytelp
add r0, r1, #1 @ no free bits
RETINSTR(mov,pc,lr)
/*
* Purpose : Find next 'zero' bit
* Prototype: int find_next_zero_bit(void *addr, int maxbit, int offset)
*/
ENTRY(find_next_zero_bit)
ands ip, r2, #7
beq .bytelp @ If new byte, goto old routine
ldrb r3, [r0, r2, lsr#3]
eor r3, r3, #0xff @ now looking for a 1 bit
movs r3, r3, lsr ip @ shift off unused bits
orreq r2, r2, #7 @ if zero, then no bits here
addeq r2, r2, #1 @ align bit pointer
beq .bytelp @ loop for next bit
/*
* One or more bits in the LSB of r3 are assumed to be set.
*/
.found: tst r3, #0x0f
addeq r2, r2, #4
movne r3, r3, lsl #4
tst r3, #0x30
addeq r2, r2, #2
movne r3, r3, lsl #2
tst r3, #0x40
addeq r2, r2, #1
mov r0, r2
RETINSTR(mov,pc,lr)
可以发现它的操作竟然是先将数字进行反转 即0->1 1->0后对1进行搜索
那简单的修改一下就应该能够搞定了
在代码后面加入下面代码
/*
* Purpose : Find a 'one' bit
* Prototype: int find_first_bit(void *addr, int maxbit);
*/
ENTRY(find_first_bit)
mov r2, #0
.bbytelp: ldrb r3, [r0, r2, lsr #3]
movs r3, r3 // 将xor改成movs 触发标志寄存器 保证下面的bne正确跳转
bne .bfound @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
cmp r2, r1 @ any more?
bcc .bbytelp
add r0, r1, #1 @ no free bits
RETINSTR(mov,pc,lr)
/*
* Purpose : Find next 'one' bit
* Prototype: int find_next_bit(void *addr, int maxbit, int offset)
*/
ENTRY(find_next_bit)
ands ip, r2, #7
beq .bbytelp @ If new byte, goto old routine
ldrb r3, [r0, r2, lsr#3]
movs r3, r3, lsr ip @ shift off unused bits
// 去掉了xor
orreq r2, r2, #7 @ if zero, then no bits here
addeq r2, r2, #1 @ align bit pointer
beq .bbytelp @ loop for next bit
/*
* One or more bits in the LSB of r3 are assumed to be set.
*/
.bfound: tst r3, #0x0f
addeq r2, r2, #4
movne r3, r3, lsl #4
tst r3, #0x30
addeq r2, r2, #2
movne r3, r3, lsl #2
tst r3, #0x40
addeq r2, r2, #1
mov r0, r2
RETINSTR(mov,pc,lr)