aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/kern_clock.c4
-rw-r--r--sys/kern/kern_clocksource.c6
-rw-r--r--sys/kern/kern_tc.c9
-rw-r--r--sys/kern/kern_timeout.c4
-rw-r--r--sys/sys/callout.h2
-rw-r--r--sys/sys/timetc.h6
6 files changed, 22 insertions, 9 deletions
diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c
index 7fb70d0d11c8..192ec6021501 100644
--- a/sys/kern/kern_clock.c
+++ b/sys/kern/kern_clock.c
@@ -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();
diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
index 7654acee4e2e..e366ef9583d2 100644
--- a/sys/kern/kern_clocksource.c
+++ b/sys/kern/kern_clocksource.c
@@ -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, int idle)
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);
diff --git a/sys/kern/kern_tc.c b/sys/kern/kern_tc.c
index 811b24f30e53..7a34a52470f7 100644
--- a/sys/kern/kern_tc.c
+++ b/sys/kern/kern_tc.c
@@ -87,6 +87,8 @@ static struct timehands *volatile timehands = &th0;
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();
diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c
index 569779235481..89fe544894d4 100644
--- a/sys/kern/kern_timeout.c
+++ b/sys/kern/kern_timeout.c
@@ -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 ){
diff --git a/sys/sys/callout.h b/sys/sys/callout.h
index 8fcd06e4f151..c0077a89774d 100644
--- a/sys/sys/callout.h
+++ b/sys/sys/callout.h
@@ -96,7 +96,7 @@ int callout_schedule_on(struct callout *, int, int);
#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
diff --git a/sys/sys/timetc.h b/sys/sys/timetc.h
index 3249788563e1..dc1dea408c6e 100644
--- a/sys/sys/timetc.h
+++ b/sys/sys/timetc.h
@@ -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