summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-10-26 18:46:03 +0000
committerian <ian@FreeBSD.org>2014-10-26 18:46:03 +0000
commit42ed59292e6b1396cd7ee9e0c052b7f332c7f5bf (patch)
tree93e3863681ab284df89f3f754c06928e1771e6ed
parente9593a964787e6a18ba95dd130bd84865689b764 (diff)
downloadFreeBSD-src-42ed59292e6b1396cd7ee9e0c052b7f332c7f5bf.zip
FreeBSD-src-42ed59292e6b1396cd7ee9e0c052b7f332c7f5bf.tar.gz
MFC r272528: Make kevent(2) periodic timer events more reliably periodic.
-rw-r--r--sys/kern/kern_event.c13
-rw-r--r--sys/sys/event.h1
2 files changed, 9 insertions, 5 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 3ad5738..8ab59bb 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -541,9 +541,9 @@ filt_timerexpire(void *knx)
if ((kn->kn_flags & EV_ONESHOT) != EV_ONESHOT) {
calloutp = (struct callout *)kn->kn_hook;
- callout_reset_sbt_on(calloutp,
- timer2sbintime(kn->kn_sdata), 0 /* 1ms? */,
- filt_timerexpire, kn, PCPU_GET(cpuid), 0);
+ *kn->kn_ptr.p_nexttime += timer2sbintime(kn->kn_sdata);
+ callout_reset_sbt_on(calloutp, *kn->kn_ptr.p_nexttime, 0,
+ filt_timerexpire, kn, PCPU_GET(cpuid), C_ABSOLUTE);
}
}
@@ -575,11 +575,13 @@ filt_timerattach(struct knote *kn)
kn->kn_flags |= EV_CLEAR; /* automatically set */
kn->kn_status &= ~KN_DETACHED; /* knlist_add clears it */
+ kn->kn_ptr.p_nexttime = malloc(sizeof(sbintime_t), M_KQUEUE, M_WAITOK);
calloutp = malloc(sizeof(*calloutp), M_KQUEUE, M_WAITOK);
callout_init(calloutp, CALLOUT_MPSAFE);
kn->kn_hook = calloutp;
- callout_reset_sbt_on(calloutp, to, 0 /* 1ms? */,
- filt_timerexpire, kn, PCPU_GET(cpuid), 0);
+ *kn->kn_ptr.p_nexttime = to + sbinuptime();
+ callout_reset_sbt_on(calloutp, *kn->kn_ptr.p_nexttime, 0,
+ filt_timerexpire, kn, PCPU_GET(cpuid), C_ABSOLUTE);
return (0);
}
@@ -593,6 +595,7 @@ filt_timerdetach(struct knote *kn)
calloutp = (struct callout *)kn->kn_hook;
callout_drain(calloutp);
free(calloutp, M_KQUEUE);
+ free(kn->kn_ptr.p_nexttime, M_KQUEUE);
old = atomic_fetch_sub_explicit(&kq_ncallouts, 1, memory_order_relaxed);
KASSERT(old > 0, ("Number of callouts cannot become negative"));
kn->kn_status |= KN_DETACHED; /* knlist_remove sets it */
diff --git a/sys/sys/event.h b/sys/sys/event.h
index b2f9c76..0282c7d 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -214,6 +214,7 @@ struct knote {
struct proc *p_proc; /* proc pointer */
struct aiocblist *p_aio; /* AIO job pointer */
struct aioliojob *p_lio; /* LIO job pointer */
+ sbintime_t *p_nexttime; /* next timer event fires at */
} kn_ptr;
struct filterops *kn_fop;
void *kn_hook;
OpenPOWER on IntegriCloud