svn commit: r238425 - in projects/calloutng/sys: kern sys
Davide Italiano
davide at FreeBSD.org
Fri Jul 13 14:02:05 UTC 2012
Author: davide
Date: Fri Jul 13 14:02:05 2012
New Revision: 238425
URL: http://svn.freebsd.org/changeset/base/238425
Log:
Fix an issue related to old periodic timers. The code in kern_clocksource.c
uses interrupt to keep track of time, and this time may not match with
binuptime(). In order to address such incoerency, switch periodic timers to
binuptime(). While here, modify callout_process() so that it takes present
time as argument avoiding to call binuptime() twice even though it's not
strictly needed.
Reviewed by: mav
Modified:
projects/calloutng/sys/kern/kern_clock.c
projects/calloutng/sys/kern/kern_clocksource.c
projects/calloutng/sys/kern/kern_timeout.c
projects/calloutng/sys/sys/callout.h
Modified: projects/calloutng/sys/kern/kern_clock.c
==============================================================================
--- projects/calloutng/sys/kern/kern_clock.c Fri Jul 13 13:24:33 2012 (r238424)
+++ projects/calloutng/sys/kern/kern_clock.c Fri Jul 13 14:02:05 2012 (r238425)
@@ -425,6 +425,7 @@ initclocks(dummy)
void
hardclock_cpu(int usermode)
{
+ struct bintime now;
struct pstats *pstats;
struct thread *td = curthread;
struct proc *p = td->td_proc;
@@ -459,7 +460,8 @@ hardclock_cpu(int usermode)
if (td->td_intr_frame != NULL)
PMC_SOFT_CALL_TF( , , clock, hard, td->td_intr_frame);
#endif
- callout_process();
+ binuptime(&now);
+ callout_process(&now);
}
/*
Modified: projects/calloutng/sys/kern/kern_clocksource.c
==============================================================================
--- projects/calloutng/sys/kern/kern_clocksource.c Fri Jul 13 13:24:33 2012 (r238424)
+++ projects/calloutng/sys/kern/kern_clocksource.c Fri Jul 13 14:02:05 2012 (r238425)
@@ -239,7 +239,7 @@ handleevents(struct bintime *now, int fa
if (bintime_cmp(now, &state->nextcall, >=) &&
(state->nextcall.sec != -1)) {
state->nextcall.sec = -1;
- callout_process();
+ callout_process(now);
}
#ifdef KDTRACE_HOOKS
@@ -363,13 +363,12 @@ timercb(struct eventtimer *et, void *arg
next = &state->nexttick;
} else
next = &nexttick;
- if (periodic) {
- now = *next; /* Ex-next tick time becomes present time. */
+ binuptime(&now);
+ if (periodic) {
+ *next = now;
bintime_add(next, &timerperiod); /* Next tick in 1 period. */
- } else {
- binuptime(&now); /* Get present time from hardware. */
- next->sec = -1; /* Next tick is not scheduled yet. */
- }
+ } else
+ next->sec = -1; /* Next tick is not scheduled yet. */
state->now = now;
CTR4(KTR_SPARE2, "intr at %d: now %d.%08x%08x",
curcpu, (int)(now.sec), (u_int)(now.frac >> 32),
@@ -720,11 +719,7 @@ cpu_initclocks_ap(void)
state = DPCPU_PTR(timerstate);
binuptime(&now);
ET_HW_LOCK(state);
- if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 && periodic) {
- state->now = nexttick;
- bintime_sub(&state->now, &timerperiod);
- } else
- state->now = now;
+ state->now = now;
hardclock_sync(curcpu);
handleevents(&state->now, 2);
if (timer->et_flags & ET_FLAGS_PERCPU)
Modified: projects/calloutng/sys/kern/kern_timeout.c
==============================================================================
--- projects/calloutng/sys/kern/kern_timeout.c Fri Jul 13 13:24:33 2012 (r238424)
+++ projects/calloutng/sys/kern/kern_timeout.c Fri Jul 13 14:02:05 2012 (r238425)
@@ -349,9 +349,9 @@ get_bucket(struct bintime *bt)
}
void
-callout_process(void)
+callout_process(struct bintime *now)
{
- struct bintime max, min, next, now, tmp_max, tmp_min;
+ struct bintime max, min, next, tmp_max, tmp_min;
struct callout *tmp;
struct callout_cpu *cc;
struct callout_tailq *sc;
@@ -364,10 +364,9 @@ callout_process(void)
need_softclock = 0;
cc = CC_SELF();
mtx_lock_spin_flags(&cc->cc_lock, MTX_QUIET);
- binuptime(&now);
cpu = curcpu;
first = callout_hash(&cc->cc_lastscan);
- last = callout_hash(&now);
+ last = callout_hash(now);
/*
* Check if we wrapped around the entire wheel from the last scan.
* In case, we need to scan entirely the wheel for pending callouts.
@@ -380,7 +379,7 @@ callout_process(void)
TAILQ_FOREACH(tmp, sc, c_links.tqe) {
next = tmp->c_time;
bintime_sub(&next, &tmp->c_precision);
- if (bintime_cmp(&next, &now, <=)) {
+ if (bintime_cmp(&next, now, <=)) {
/*
* Consumer told us the callout may be run
* directly from hardware interrupt context.
@@ -445,7 +444,7 @@ callout_process(void)
if (max.sec == TIME_T_MAX) {
next.sec = 0;
next.frac = (uint64_t)1 << (64 - 2);
- bintime_add(&next, &now);
+ bintime_add(&next, now);
} else {
/*
* Now that we found something to aggregate, schedule an
@@ -461,7 +460,7 @@ callout_process(void)
cc->cc_firstevent = next;
if (callout_new_inserted != NULL)
(*callout_new_inserted)(cpu, next);
- cc->cc_lastscan = now;
+ cc->cc_lastscan = *now;
mtx_unlock_spin_flags(&cc->cc_lock, MTX_QUIET);
/*
* swi_sched acquires the thread lock, so we don't want to call it
Modified: projects/calloutng/sys/sys/callout.h
==============================================================================
--- projects/calloutng/sys/sys/callout.h Fri Jul 13 13:24:33 2012 (r238424)
+++ projects/calloutng/sys/sys/callout.h Fri Jul 13 14:02:05 2012 (r238425)
@@ -113,7 +113,7 @@ int callout_schedule_on(struct callout *
callout_schedule_on((c), (on_tick), PCPU_GET(cpuid))
#define callout_stop(c) _callout_stop_safe(c, 0)
int _callout_stop_safe(struct callout *, int);
-void callout_process(void);
+void callout_process(struct bintime *);
extern void (*callout_new_inserted)(int cpu, struct bintime bt);
#endif
More information about the svn-src-projects
mailing list