#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 sched_find_first_bit(const unsigned long *b) { if (unlikely(b[0])) return __ffs(b[0]); if (unlikely(b[1])) return __ffs(b[1]) + 32; if (unlikely(b[2])) return __ffs(b[2]) + 64; if (b[3]) return __ffs(b[3]) + 96; return __ffs(b[4]) + 128; } #define rdtscll(val) \ __asm__ __volatile__("rdtsc" : "=A" (val)) #define rdtsc(low,high) \ __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high)) static unsigned long array[5]; #define ITER 1000000 /* 1,000,000 times */ void testit(unsigned long *array, unsigned long long clock) { unsigned long long s1; unsigned long long e1; unsigned long long s2; unsigned long long e2; unsigned long long t1; unsigned long long t2; double f1; double f2; int i; int x; rdtscll(s1); for (i=0; i < ITER; i++) x = find_first_bit(array,140); rdtscll(e1); rdtscll(s2); for (i=0; i < ITER; i++) x = sched_find_first_bit(array); rdtscll(e2); t1 = e1 - s1; t2 = e2 - s2; f1 = (float)t1 / (float)clock; f2 = (float)t2 / (float)clock; /* * Since ITER is 1,000,000 the times will be in us. */ printf("generic ffb: %08lx:%08lx\n", (unsigned long)(t1>>32),(unsigned long)t1); printf("time: %.09fus\n",f1); printf("sched ffb: %08lx:%08lx\n", (unsigned long)(t2>>32),(unsigned long)t2); printf("time: %.09fus\n",f2); } 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; array[4] = 0x80000000; printf("last bit set\n"); testit(array,clock); array[0] = 0x00000001; printf("\nfirst bit set\n"); testit(array,clock); exit(0); }