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
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to