最近在重翻些FS的代码,file open的时候首先要获取unused fd, 例如如下:
/* * Find an empty file descriptor entry, and mark it busy. */int get_unused_fd(void){ struct files_struct * files = current->files; int fd, error;
error = -EMFILE; write_lock(&files->file_lock);
repeat: fd = find_next_zero_bit(files->open_fds, files->max_fdset, files->next_fd);
........................
这里重点研究下find_next_zero_bit,这里是从open_fds中找到空隙的fd,翻开这块内部代码:
先温习下这里的几个重点asm命令(intel):
bsfl:
bsfl source, destination
从右向左(0->15,31位)在source中找到非0的位置,并保存在destination
scasl:
扫描EDI(隐含源)和EAX的匹配度,和repe,repne结合
比如 repe; scasl;
含义:如果EDI和EAX等值,继续loop, until到不匹配
static __inline__ int find_next_zero_bit (void * addr, int size, int offset){ unsigned long * p = ((unsigned long *) addr) + (offset >> 5); int set = 0, bit = offset & 31, res; if (bit) { /* * Look for zero in first byte */ __asm__(
//从offset开始的INT查找bit 1,
"bsfl %1,%0/n/t" "jne 1f/n/t" "movl $32, %0/n" "1:" : "=r" (set)
// 注意取反,目标是look zero, : "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 - (unsigned long *) addr)); return (offset + set + res);}
/* * Find-bit routines.. */static __inline__ int find_first_zero_bit(void * addr, unsigned size){ int d0, d1, d2; int res;
if (!size) return 0; /* This looks at memory. Mark it volatile to tell gcc not to move it around */ __asm__ __volatile__(
// EAX赋值0xFFFFFFFF "movl $-1,%