Date: Tue, 14 Sep 2010 08:48:06 +0000 (UTC) From: Alexander Motin <mav@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r212603 - in head/sys: kern sys Message-ID: <201009140848.o8E8m6V0073401@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: mav Date: Tue Sep 14 08:48:06 2010 New Revision: 212603 URL: http://svn.freebsd.org/changeset/base/212603 Log: Make kern_tc.c provide minimum frequency of tc_ticktock() calls, required to handle current timecounter wraps. Make kern_clocksource.c to honor that requirement, scheduling sleeps on first CPU for no more then specified period. Allow other CPUs to sleep up to 1/4 second (for any case). Modified: head/sys/kern/kern_clock.c head/sys/kern/kern_clocksource.c head/sys/kern/kern_tc.c head/sys/kern/kern_timeout.c head/sys/sys/callout.h head/sys/sys/timetc.h Modified: head/sys/kern/kern_clock.c ============================================================================== --- head/sys/kern/kern_clock.c Tue Sep 14 07:09:24 2010 (r212602) +++ head/sys/kern/kern_clock.c Tue Sep 14 08:48:06 2010 (r212603) @@ -457,7 +457,7 @@ hardclock(int usermode, uintfptr_t pc) atomic_add_int((volatile int *)&ticks, 1); hardclock_cpu(usermode); - tc_ticktock(); + tc_ticktock(1); cpu_tick_calibration(); /* * If no separate statistics clock is available, run it from here. @@ -538,7 +538,7 @@ hardclock_anycpu(int cnt, int usermode) if (newticks > 0) { /* Dangerous and no need to call these things concurrently. */ if (atomic_cmpset_acq_int(&global_hardclock_run, 0, 1)) { - tc_ticktock(); + tc_ticktock(newticks); #ifdef DEVICE_POLLING /* This is very short and quick. */ hardclock_device_poll(); Modified: head/sys/kern/kern_clocksource.c ============================================================================== --- head/sys/kern/kern_clocksource.c Tue Sep 14 07:09:24 2010 (r212602) +++ head/sys/kern/kern_clocksource.c Tue Sep 14 08:48:06 2010 (r212603) @@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$"); #include <sys/smp.h> #include <sys/sysctl.h> #include <sys/timeet.h> +#include <sys/timetc.h> #include <machine/atomic.h> #include <machine/clock.h> @@ -247,7 +248,10 @@ getnextcpuevent(struct bintime *event, i state = DPCPU_PTR(timerstate); *event = state->nexthard; if (idle) { /* If CPU is idle - ask callouts for how long. */ - skip = callout_tickstofirst() - 1; + skip = 4; + if (curcpu == CPU_FIRST() && tc_min_ticktock_freq > skip) + skip = tc_min_ticktock_freq; + skip = callout_tickstofirst(hz / skip) - 1; CTR2(KTR_SPARE2, "skip at %d: %d", curcpu, skip); tmp = hardperiod; bintime_mul(&tmp, skip); Modified: head/sys/kern/kern_tc.c ============================================================================== --- head/sys/kern/kern_tc.c Tue Sep 14 07:09:24 2010 (r212602) +++ head/sys/kern/kern_tc.c Tue Sep 14 08:48:06 2010 (r212603) @@ -87,6 +87,8 @@ static struct timehands *volatile timeha struct timecounter *timecounter = &dummy_timecounter; static struct timecounter *timecounters = &dummy_timecounter; +int tc_min_ticktock_freq = 1; + time_t time_second = 1; time_t time_uptime = 1; @@ -482,6 +484,8 @@ tc_windup(void) if (th->th_counter != timecounter) { th->th_counter = timecounter; th->th_offset_count = ncount; + tc_min_ticktock_freq = max(1, timecounter->tc_frequency / + (((uint64_t)timecounter->tc_counter_mask + 1) / 3)); } /*- @@ -767,11 +771,12 @@ static int tc_tick; SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tc_tick, 0, ""); void -tc_ticktock(void) +tc_ticktock(int cnt) { static int count; - if (++count < tc_tick) + count += cnt; + if (count < tc_tick) return; count = 0; tc_windup(); Modified: head/sys/kern/kern_timeout.c ============================================================================== --- head/sys/kern/kern_timeout.c Tue Sep 14 07:09:24 2010 (r212602) +++ head/sys/kern/kern_timeout.c Tue Sep 14 08:48:06 2010 (r212603) @@ -280,7 +280,7 @@ callout_tick(void) } int -callout_tickstofirst(void) +callout_tickstofirst(int limit) { struct callout_cpu *cc; struct callout *c; @@ -291,7 +291,7 @@ callout_tickstofirst(void) cc = CC_SELF(); mtx_lock_spin_flags(&cc->cc_lock, MTX_QUIET); curticks = cc->cc_ticks; - while( skip < ncallout && skip < hz/8 ) { + while( skip < ncallout && skip < limit ) { sc = &cc->cc_callwheel[ (curticks+skip) & callwheelmask ]; /* search scanning ticks */ TAILQ_FOREACH( c, sc, c_links.tqe ){ Modified: head/sys/sys/callout.h ============================================================================== --- head/sys/sys/callout.h Tue Sep 14 07:09:24 2010 (r212602) +++ head/sys/sys/callout.h Tue Sep 14 08:48:06 2010 (r212603) @@ -96,7 +96,7 @@ int callout_schedule_on(struct callout * #define callout_stop(c) _callout_stop_safe(c, 0) int _callout_stop_safe(struct callout *, int); void callout_tick(void); -int callout_tickstofirst(void); +int callout_tickstofirst(int limit); extern void (*callout_new_inserted)(int cpu, int ticks); #endif Modified: head/sys/sys/timetc.h ============================================================================== --- head/sys/sys/timetc.h Tue Sep 14 07:09:24 2010 (r212602) +++ head/sys/sys/timetc.h Tue Sep 14 08:48:06 2010 (r212603) @@ -65,11 +65,15 @@ struct timecounter { }; extern struct timecounter *timecounter; +extern int tc_min_ticktock_freq; /* + * Minimal tc_ticktock() call frequency, + * required to handle counter wraps. + */ u_int64_t tc_getfrequency(void); void tc_init(struct timecounter *tc); void tc_setclock(struct timespec *ts); -void tc_ticktock(void); +void tc_ticktock(int cnt); void cpu_tick_calibration(void); #ifdef SYSCTL_DECL
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201009140848.o8E8m6V0073401>