#include #include #include #include #define unlikely(x) __builtin_expect(!!(x), 0) static inline int find_first_bit(const unsigned long *addr, unsigned size) { int d0, d1; int res; /* This looks at memory. Mark it volatile to tell gcc not to move it around */ __asm__ __volatile__( "xorl %%eax,%%eax\n\t" "repe; scasl\n\t" "jz 1f\n\t" "leal -4(%%edi),%%edi\n\t" "bsfl (%%edi),%%eax\n" "1:\tsubl %%ebx,%%edi\n\t" "shll $3,%%edi\n\t" "addl %%edi,%%eax" :"=a" (res), "=&c" (d0), "=&D" (d1) :"1" ((size + 31) >> 5), "2" (addr), "b" (addr) : "memory"); return res; } static inline unsigned long __ffs(unsigned long word) { __asm__("bsfl %1,%0" :"=r" (word) :"rm" (word)); return word; } static inline int my_find_first_bit(const unsigned long *b, unsigned size) { int x = 0; do { if (*b) return __ffs(*b) + x; b++; if (x >= size) break; x += 32; } while (1); return x; } static inline int my_find_first_bit2(const unsigned long *b, unsigned size) { int x = 0; do { if (unlikely(*b)) return __ffs(*b) + x; b++; if (x >= size) break; x += 32; } while (1); return x; } #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) #define rdtsc(low,high) \ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) #define BITSIZE 310 static unsigned long array[((BITSIZE)>>5)+1]; #define ITER 1000000 /* 1,000,000 times */ void testit(unsigned long *array, unsigned long long clock) { unsigned long long s; unsigned long long e; unsigned long long t; double f; int i; int x; /* * Since ITER is 1,000,000 the times will be in us. */ /* * Make sure that the output is correct. */ printf("ffb=%d my=%d my2=%d\n", find_first_bit(array,BITSIZE), my_find_first_bit(array,BITSIZE), my_find_first_bit2(array,BITSIZE)); rdtscll(s); for (i=0; i < ITER; i++) x = find_first_bit(array,BITSIZE); rdtscll(e); t = e - s; f = (float)t / (float)clock; printf("generic ffb: %08lx:%08lx\n", (unsigned long)(t>>32),(unsigned long)t); printf("time: %.09fus\n",f); rdtscll(s); for (i=0; i < ITER; i++) x = my_find_first_bit(array,BITSIZE); rdtscll(e); t = e - s; f = (float)t / (float)clock; printf("my ffb: %08lx:%08lx\n", (unsigned long)(t>>32),(unsigned long)t); printf("time: %.09fus\n",f); rdtscll(s); for (i=0; i < ITER; i++) x = my_find_first_bit2(array,BITSIZE); rdtscll(e); t = e - s; f = (float)t / (float)clock; printf("my ffb 2: %08lx:%08lx\n", (unsigned long)(t>>32),(unsigned long)t); printf("time: %.09fus\n",f); } int main(int argc, char **argv) { unsigned long long s; unsigned long long e; unsigned long long t; unsigned long long clock; /* * Calculate BS time, just to get an * idea of the tsc speed. */ rdtscll(s); sleep(8); rdtscll(e); t = e - s; t >>= 3; printf("clock speed = %08lx:%08lx %llu ticks per second\n", (unsigned long)(t>>32),(unsigned long)t, t); clock = t; printf("\nno bit set\n"); testit(array,clock); array[BITSIZE>>5] = 0x80000000; printf("\nlast bit set\n"); testit(array,clock); array[4] = 0x80000000; printf("\nmiddle bit set\n"); testit(array,clock); array[0] = 0x00000001; printf("\nfirst bit set\n"); testit(array,clock); exit(0); }