diff -ur -x compile -x _* freebsd/src/sys/kern/kern_tc.c phk/phk_dev/sys/kern/kern_tc.c --- freebsd/src/sys/kern/kern_tc.c Tue Oct 12 09:11:40 2004 +++ phk/phk_dev/sys/kern/kern_tc.c Fri Nov 19 10:10:30 2004 @@ -782,3 +782,144 @@ } SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL) + + +static void +tc_nanodelay(u_int nano) +{ + struct timespec t0, t1; + + nanouptime(&t1); + t1.tv_nsec += nano; + if (t1.tv_nsec >= 1000000000) { + t1.tv_nsec -= 1000000000; + t1.tv_sec++; + } + while (1) { + nanouptime(&t0); + if (t0.tv_sec > t1.tv_sec) + return; + if (t0.tv_sec == t1.tv_sec && t0.tv_nsec >= t1.tv_nsec) + return; + } +} + +typedef void nanodelay_t(u_int arg); + +#define N_NANODELAY_BUCKETS 1000 +#define N_NANODELAY_ITER 1000 +#define N_NANODELAY_SHIFT 3 + +#define ns_to_bucket(n) ((n) >> N_NANODELAY_SHIFT) + +static nanodelay_t *nanodelay_funcs[N_NANODELAY_BUCKETS]; +static u_int nanodelay_args[N_NANODELAY_BUCKETS]; +static u_char nanodelay_mode[N_NANODELAY_BUCKETS]; + +void +nanodelay(u_int nano) +{ + u_int u; + + u = ns_to_bucket(nano); + if (u < N_NANODELAY_BUCKETS) + nanodelay_funcs[u](nanodelay_args[u]); + else + tc_nanodelay(nano); +} + +static void +set_nanodelay(nanodelay_t *func, u_int bucket, u_int arg, const char *name) +{ + u_int u; + + nanodelay_funcs[bucket] = func; + nanodelay_args[bucket] = arg; + nanodelay_mode[bucket] = 1; + for (u = bucket; u != 0;) { + u--; + if (nanodelay_mode[u]) + break; + nanodelay_funcs[u] = func; + nanodelay_args[u] = arg; + } + if (bootverbose) + printf("nanodelay[%u...%u] = %s(%u)\n", + u << N_NANODELAY_SHIFT, bucket << N_NANODELAY_SHIFT, + name, arg); +} + +static void +register_nanodelay(nanodelay_t *func, u_int arg_low, u_int arg_high, const char *name) +{ + struct bintime t0, t1; + struct timespec ts; + u_int u, bucket, lbucket; + int i; + + lbucket = 0; + for (u = arg_low; u <= arg_high; u++) { + binuptime(&t0); + for (i = 0; i < N_NANODELAY_ITER; i++) + func(u); + binuptime(&t1); + bintime_sub(&t1, &t0); + t1.frac /= N_NANODELAY_ITER; + bintime2timespec(&t1, &ts); + if (ts.tv_sec > 0) + continue; + bucket = ns_to_bucket(ts.tv_nsec); + if (bucket > 2 * N_NANODELAY_BUCKETS) + break; + if (bucket < N_NANODELAY_BUCKETS && lbucket != bucket) + set_nanodelay(func, bucket, u, name); + lbucket = bucket; + } +} + +u_int njustret; + +static void +nanodelay_justret(u_int arg) +{ + + njustret++; +} + +static void +nanodelay_loop(u_int arg) +{ + while (arg-- > 0) + ; +} + +static void +nanodelay_loopcall(u_int arg) +{ + while (arg-- > 0) + nanodelay_justret(0); +} + +static void +nanodelay_loopcall2(u_int arg) +{ + while (arg-- > 0) + nanodelay_loopcall(arg); +} + +static void +initnanodelay(void *dummy) +{ + int i; + + for (i = 0; i < N_NANODELAY_BUCKETS; i++) { + nanodelay_funcs[i] = tc_nanodelay; + nanodelay_args[i] = i; + } + register_nanodelay(nanodelay_justret, 0, 0, "justret"); + register_nanodelay(nanodelay_loop, 0, 100, "loop"); + /* register_nanodelay(nanodelay_loopcall, 0, 100, "loopcall"); */ + register_nanodelay(nanodelay_loopcall2, 0, 100, "loopcall2"); +} + +SYSINIT(nanodelay, SI_SUB_CLOCKS, SI_ORDER_SECOND, initnanodelay, NULL) Only in phk/phk_dev/sys/modules: Makefile.orig Only in phk/phk_dev/sys/modules: ata Only in phk/phk_dev/sys/sys: modules diff -ur -x compile -x _* freebsd/src/sys/sys/systm.h phk/phk_dev/sys/sys/systm.h --- freebsd/src/sys/sys/systm.h Mon Nov 1 10:35:01 2004 +++ phk/phk_dev/sys/sys/systm.h Fri Nov 19 10:10:30 2004 @@ -306,7 +306,7 @@ int uminor(dev_t dev); int umajor(dev_t dev); -/* XXX: Should be void nanodelay(u_int nsec); */ +void nanodelay(u_int nsec); void DELAY(int usec); /* Only in phk/phk_dev/sys/vm: device_pager.c__ Only in phk/phk_dev/sys: x.d