summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_clocksource.c
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2010-09-21 17:37:28 +0000
committermav <mav@FreeBSD.org>2010-09-21 17:37:28 +0000
commit10e1b075c5af804a564e0935e5ac94b89c03dedd (patch)
tree01eafa07de587ca1fc9ffaf2ce9f8070b8f61cfd /sys/kern/kern_clocksource.c
parent506226a8f9b1803546677a06aadcdf7aadd8f967 (diff)
downloadFreeBSD-src-10e1b075c5af804a564e0935e5ac94b89c03dedd.zip
FreeBSD-src-10e1b075c5af804a564e0935e5ac94b89c03dedd.tar.gz
If new callout scheduled to another CPU and we are using global timer,
there is high probability that timer is already programmed by some other CPU. Especially by one that registered this callout, and so active now.
Diffstat (limited to 'sys/kern/kern_clocksource.c')
-rw-r--r--sys/kern/kern_clocksource.c10
1 files changed, 7 insertions, 3 deletions
diff --git a/sys/kern/kern_clocksource.c b/sys/kern/kern_clocksource.c
index 455564b..e9a7c9d 100644
--- a/sys/kern/kern_clocksource.c
+++ b/sys/kern/kern_clocksource.c
@@ -785,14 +785,18 @@ cpu_new_callout(int cpu, int ticks)
}
/*
* If timer is periodic - just update next event time for target CPU.
+ * If timer is global - there is chance it is already programmed.
*/
- if (periodic) {
+ if (periodic || (timer->et_flags & ET_FLAGS_PERCPU) == 0) {
state->nextevent = state->nexthard;
tmp = hardperiod;
bintime_mul(&tmp, ticks - 1);
bintime_add(&state->nextevent, &tmp);
- ET_HW_UNLOCK(state);
- return;
+ if (periodic ||
+ bintime_cmp(&state->nextevent, &nexttick, >=)) {
+ ET_HW_UNLOCK(state);
+ return;
+ }
}
/*
* Otherwise we have to wake that CPU up, as we can't get present
OpenPOWER on IntegriCloud