Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files. =================================================================== RCS file: /ftp/cvs/cvsroot/src/sys/kern/kern_tc.c,v rcsdiff: /ftp/cvs/cvsroot/src/sys/kern/kern_tc.c,v: warning: Unknown phrases like `commitid ...;' are present. retrieving revision 1.21.2.4 retrieving revision 1.22 diff -u -p -r1.21.2.4 -r1.22 --- src/sys/kern/kern_tc.c 2008/02/18 21:06:46 1.21.2.4 +++ src/sys/kern/kern_tc.c 2007/11/15 20:12:04 1.22 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_tc.c,v 1.21.2.4 2008/02/18 21:06:46 mjf Exp $ */ +/* $NetBSD: kern_tc.c,v 1.22 2007/11/15 20:12:04 ad Exp $ */ /*- * ---------------------------------------------------------------------------- @@ -11,11 +11,12 @@ #include /* __FBSDID("$FreeBSD: src/sys/kern/kern_tc.c,v 1.166 2005/09/19 22:16:31 andre Exp $"); */ -__KERNEL_RCSID(0, "$NetBSD: kern_tc.c,v 1.21.2.4 2008/02/18 21:06:46 mjf Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_tc.c,v 1.22 2007/11/15 20:12:04 ad Exp $"); #include "opt_ntp.h" #include +#ifdef __HAVE_TIMECOUNTER /* XXX */ #include #include /* XXX just to get AB_VERBOSE */ #include @@ -26,8 +27,6 @@ __KERNEL_RCSID(0, "$NetBSD: kern_tc.c,v #include #include #include -#include -#include /* * A large step happens on boot. This constant detects such steps. @@ -98,16 +97,13 @@ static struct bintime timebasebin; static int timestepwarnings; -extern kmutex_t time_lock; -static kmutex_t tc_windup_lock; - #ifdef __FreeBSD__ SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW, ×tepwarnings, 0, ""); #endif /* __FreeBSD__ */ /* - * sysctl helper routine for kern.timercounter.hardware + * sysctl helper routine for kern.timercounter.current */ static int sysctl_kern_timecounter_hardware(SYSCTLFN_ARGS) @@ -132,14 +128,12 @@ sysctl_kern_timecounter_hardware(SYSCTLF strncmp(newname, tc->tc_name, sizeof(newname)) == 0) return error; - if (l != NULL && (error = kauth_authorize_system(l->l_cred, - KAUTH_SYSTEM_TIME, KAUTH_REQ_SYSTEM_TIME_TIMECOUNTERS, newname, - NULL, NULL)) != 0) + if (l != NULL && (error = kauth_authorize_generic(l->l_cred, + KAUTH_GENERIC_ISSUSER, NULL)) != 0) return (error); if (!cold) mutex_enter(&time_lock); - error = EINVAL; for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) { if (strcmp(newname, newtc->tc_name) != 0) continue; @@ -148,8 +142,8 @@ sysctl_kern_timecounter_hardware(SYSCTLF (void)newtc->tc_get_timecount(newtc); timecounter = newtc; error = 0; - break; - } + } else + error = EINVAL; if (!cold) mutex_exit(&time_lock); return error; @@ -235,21 +229,18 @@ SYSCTL_SETUP(sysctl_timecounter_setup, " } } -#ifdef TC_COUNTERS #define TC_STATS(name) \ static struct evcnt n##name = \ EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "timecounter", #name); \ EVCNT_ATTACH_STATIC(n##name) + TC_STATS(binuptime); TC_STATS(nanouptime); TC_STATS(microuptime); TC_STATS(bintime); TC_STATS(nanotime); TC_STATS(microtime); TC_STATS(getbinuptime); TC_STATS(getnanouptime); TC_STATS(getmicrouptime); TC_STATS(getbintime); TC_STATS(getnanotime); TC_STATS(getmicrotime); TC_STATS(setclock); -#define TC_COUNT(var) var.ev_count++ + #undef TC_STATS -#else -#define TC_COUNT(var) /* nothing */ -#endif /* TC_COUNTERS */ static void tc_windup(void); @@ -279,12 +270,14 @@ binuptime(struct bintime *bt) struct timehands *th; u_int gen; - TC_COUNT(nbinuptime); + nbinuptime.ev_count++; do { th = timehands; gen = th->th_generation; + mb_read(); *bt = th->th_offset; bintime_addx(bt, th->th_scale * tc_delta(th)); + mb_read(); } while (gen == 0 || gen != th->th_generation); } @@ -293,7 +286,7 @@ nanouptime(struct timespec *tsp) { struct bintime bt; - TC_COUNT(nnanouptime); + nnanouptime.ev_count++; binuptime(&bt); bintime2timespec(&bt, tsp); } @@ -303,7 +296,7 @@ microuptime(struct timeval *tvp) { struct bintime bt; - TC_COUNT(nmicrouptime); + nmicrouptime.ev_count++; binuptime(&bt); bintime2timeval(&bt, tvp); } @@ -312,7 +305,7 @@ void bintime(struct bintime *bt) { - TC_COUNT(nbintime); + nbintime.ev_count++; binuptime(bt); bintime_add(bt, &timebasebin); } @@ -322,7 +315,7 @@ nanotime(struct timespec *tsp) { struct bintime bt; - TC_COUNT(nnanotime); + nnanotime.ev_count++; bintime(&bt); bintime2timespec(&bt, tsp); } @@ -332,7 +325,7 @@ microtime(struct timeval *tvp) { struct bintime bt; - TC_COUNT(nmicrotime); + nmicrotime.ev_count++; bintime(&bt); bintime2timeval(&bt, tvp); } @@ -343,11 +336,13 @@ getbinuptime(struct bintime *bt) struct timehands *th; u_int gen; - TC_COUNT(ngetbinuptime); + ngetbinuptime.ev_count++; do { th = timehands; gen = th->th_generation; + mb_read(); *bt = th->th_offset; + mb_read(); } while (gen == 0 || gen != th->th_generation); } @@ -357,11 +352,13 @@ getnanouptime(struct timespec *tsp) struct timehands *th; u_int gen; - TC_COUNT(ngetnanouptime); + ngetnanouptime.ev_count++; do { th = timehands; gen = th->th_generation; + mb_read(); bintime2timespec(&th->th_offset, tsp); + mb_read(); } while (gen == 0 || gen != th->th_generation); } @@ -371,11 +368,13 @@ getmicrouptime(struct timeval *tvp) struct timehands *th; u_int gen; - TC_COUNT(ngetmicrouptime); + ngetmicrouptime.ev_count++; do { th = timehands; gen = th->th_generation; + mb_read(); bintime2timeval(&th->th_offset, tvp); + mb_read(); } while (gen == 0 || gen != th->th_generation); } @@ -385,11 +384,13 @@ getbintime(struct bintime *bt) struct timehands *th; u_int gen; - TC_COUNT(ngetbintime); + ngetbintime.ev_count++; do { th = timehands; gen = th->th_generation; + mb_read(); *bt = th->th_offset; + mb_read(); } while (gen == 0 || gen != th->th_generation); bintime_add(bt, &timebasebin); } @@ -400,11 +401,13 @@ getnanotime(struct timespec *tsp) struct timehands *th; u_int gen; - TC_COUNT(ngetnanotime); + ngetnanotime.ev_count++; do { th = timehands; gen = th->th_generation; + mb_read(); *tsp = th->th_nanotime; + mb_read(); } while (gen == 0 || gen != th->th_generation); } @@ -414,11 +417,13 @@ getmicrotime(struct timeval *tvp) struct timehands *th; u_int gen; - TC_COUNT(ngetmicrotime); + ngetmicrotime.ev_count++; do { th = timehands; gen = th->th_generation; + mb_read(); *tvp = th->th_microtime; + mb_read(); } while (gen == 0 || gen != th->th_generation); } @@ -429,6 +434,7 @@ void tc_init(struct timecounter *tc) { u_int u; + int s; u = tc->tc_frequency / tc->tc_counter_mask; /* XXX: We need some margin here, 10% is a guess */ @@ -448,7 +454,7 @@ tc_init(struct timecounter *tc) } mutex_enter(&time_lock); - mutex_spin_enter(&tc_windup_lock); + s = splsched(); tc->tc_next = timecounters; timecounters = tc; /* @@ -457,62 +463,16 @@ tc_init(struct timecounter *tc) * worse since this timecounter may not be monotonous. */ if (tc->tc_quality >= 0 && (tc->tc_quality > timecounter->tc_quality || - (tc->tc_quality == timecounter->tc_quality && - tc->tc_frequency > timecounter->tc_frequency))) { + tc->tc_frequency > timecounter->tc_frequency)) { (void)tc->tc_get_timecount(tc); (void)tc->tc_get_timecount(tc); timecounter = tc; tc_windup(); } - mutex_spin_exit(&tc_windup_lock); + splx(s); mutex_exit(&time_lock); } -/* - * Stop using a timecounter and remove it from the timecounters list. - */ -int -tc_detach(struct timecounter *target) -{ - struct timecounter *best, *tc; - struct timecounter **tcp = NULL; - int rc = 0; - - mutex_enter(&time_lock); - for (tcp = &timecounters, tc = timecounters; - tc != NULL; - tcp = &tc->tc_next, tc = tc->tc_next) { - if (tc == target) - break; - } - if (tc == NULL) { - rc = ESRCH; - goto out; - } - *tcp = tc->tc_next; - - if (timecounter != target) - goto out; - - for (best = tc = timecounters; tc != NULL; tc = tc->tc_next) { - if (tc->tc_quality > best->tc_quality) - best = tc; - else if (tc->tc_quality < best->tc_quality) - continue; - else if (tc->tc_frequency > best->tc_frequency) - best = tc; - } - mutex_spin_enter(&tc_windup_lock); - (void)best->tc_get_timecount(best); - (void)best->tc_get_timecount(best); - timecounter = best; - tc_windup(); - mutex_spin_exit(&tc_windup_lock); -out: - mutex_exit(&time_lock); - return rc; -} - /* Report the frequency of the current timecounter. */ u_int64_t tc_getfrequency(void) @@ -524,6 +484,7 @@ tc_getfrequency(void) /* * Step our concept of UTC. This is done by modifying our estimate of * when we booted. + * XXX: not locked. */ void tc_setclock(struct timespec *ts) @@ -531,16 +492,15 @@ tc_setclock(struct timespec *ts) struct timespec ts2; struct bintime bt, bt2; - mutex_spin_enter(&tc_windup_lock); - TC_COUNT(nsetclock); + nsetclock.ev_count++; binuptime(&bt2); timespec2bintime(ts, &bt); bintime_sub(&bt, &bt2); bintime_add(&bt2, &timebasebin); timebasebin = bt; - tc_windup(); - mutex_spin_exit(&tc_windup_lock); + /* XXX fiddle all the little crinkly bits around the fiords... */ + tc_windup(); if (timestepwarnings) { bintime2timespec(&bt2, &ts2); log(LOG_INFO, "Time stepped from %jd.%09ld to %jd.%09ld\n", @@ -564,8 +524,6 @@ tc_windup(void) int i, s_update; time_t t; - KASSERT(mutex_owned(&tc_windup_lock)); - s_update = 0; /* @@ -578,7 +536,7 @@ tc_windup(void) th = tho->th_next; ogen = th->th_generation; th->th_generation = 0; - membar_producer(); + mb_write(); bcopy(tho, th, offsetof(struct timehands, th_generation)); /* @@ -678,7 +636,7 @@ tc_windup(void) */ if (++ogen == 0) ogen = 1; - membar_producer(); + mb_write(); th->th_generation = ogen; /* @@ -687,18 +645,8 @@ tc_windup(void) */ time_second = th->th_microtime.tv_sec; time_uptime = th->th_offset.sec; - membar_producer(); + mb_write(); timehands = th; - - /* - * Force users of the old timehand to move on. This is - * necessary for MP systems; we need to ensure that the - * consumers will move away from the old timehand before - * we begin updating it again when we eventually wrap - * around. - */ - if (++tho->th_generation == 0) - tho->th_generation = 1; } /* @@ -885,9 +833,7 @@ tc_ticktock(void) if (++count < tc_tick) return; count = 0; - mutex_spin_enter(&tc_windup_lock); tc_windup(); - mutex_spin_exit(&tc_windup_lock); } void @@ -895,8 +841,6 @@ inittimecounter(void) { u_int p; - mutex_init(&tc_windup_lock, MUTEX_DEFAULT, IPL_SCHED); - /* * Set the initial timeout to * max(1, ). @@ -917,3 +861,5 @@ inittimecounter(void) (void)timecounter->tc_get_timecount(timecounter); (void)timecounter->tc_get_timecount(timecounter); } + +#endif /* __HAVE_TIMECOUNTER */