summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbapt <bapt@FreeBSD.org>2014-07-18 14:27:04 +0000
committerbapt <bapt@FreeBSD.org>2014-07-18 14:27:04 +0000
commit2592b8802eee2cd380b4c8ed5056ad4bfa31172a (patch)
tree3fa67f166c1214a4d21edc2a9631030e8b52a12e
parent53306c26de321a85d416c01e88e7df1dd71db6dd (diff)
downloadFreeBSD-src-2592b8802eee2cd380b4c8ed5056ad4bfa31172a.zip
FreeBSD-src-2592b8802eee2cd380b4c8ed5056ad4bfa31172a.tar.gz
Extend kqueue's EVFILT_TIMER by adding precision unit flags support
Define the precision macros as bits sets to conform with XNU equivalent. Test fflags passed for EVFILT_TIMER and return EINVAL in case an invalid flag is passed. Phabric: https://phabric.freebsd.org/D421 Reviewed by: kib
-rw-r--r--lib/libc/sys/kqueue.223
-rw-r--r--sys/kern/kern_event.c41
-rw-r--r--sys/sys/event.h6
3 files changed, 60 insertions, 10 deletions
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index 6f637e1..f84bc05 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd April 7, 2014
+.Dd July 18, 2014
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -454,7 +454,7 @@ Establishes an arbitrary timer identified by
.Va ident .
When adding a timer,
.Va data
-specifies the timeout period in milliseconds.
+specifies the timeout period.
The timer will be periodic unless EV_ONESHOT is specified.
On return,
.Va data
@@ -465,8 +465,25 @@ There is a system wide limit on the number of timers
which is controlled by the
.Va kern.kq_calloutmax
sysctl.
+.Bl -tag -width XXNOTE_USECONDS
+.It Dv NOTE_SECONDS
+.Va data
+is in seconds.
+.It Dv NOTE_MSECONDS
+.Va data
+is in milliseconds.
+.It Dv NOTE_USECONDS
+.Va data
+is in microseconds.
+.It Dv NOTE_NSECONDS
+.Va data
+is in nanoseconds.
+.It
+.El
.Pp
-On return,
+If
+.Va fflags
+is not set, the default is milliseconds. On return,
.Va fflags
contains the events which triggered the filter.
.It Dv EVFILT_USER
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 9615d91..fc256f1 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -523,15 +523,38 @@ knote_fork(struct knlist *list, int pid)
* XXX: EVFILT_TIMER should perhaps live in kern_time.c beside the
* interval timer support code.
*/
+
+#define NOTE_TIMER_PRECMASK (NOTE_SECONDS|NOTE_MSECONDS|NOTE_USECONDS| \
+ NOTE_NSECONDS)
+
static __inline sbintime_t
-timer2sbintime(intptr_t data)
+timer2sbintime(intptr_t data, int flags)
{
+ sbintime_t modifier;
+
+ switch (flags & NOTE_TIMER_PRECMASK) {
+ case NOTE_SECONDS:
+ modifier = SBT_1S;
+ break;
+ case NOTE_MSECONDS: /* FALLTHROUGH */
+ case 0:
+ modifier = SBT_1MS;
+ break;
+ case NOTE_USECONDS:
+ modifier = SBT_1US;
+ break;
+ case NOTE_NSECONDS:
+ modifier = SBT_1NS;
+ break;
+ default:
+ return (-1);
+ }
#ifdef __LP64__
- if (data > SBT_MAX / SBT_1MS)
+ if (data > SBT_MAX / modifier)
return (SBT_MAX);
#endif
- return (SBT_1MS * data);
+ return (modifier * data);
}
static void
@@ -547,13 +570,13 @@ 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? */,
+ timer2sbintime(kn->kn_sdata, kn->kn_sfflags), 0,
filt_timerexpire, kn, PCPU_GET(cpuid), 0);
}
}
/*
- * data contains amount of time to sleep, in milliseconds
+ * data contains amount of time to sleep
*/
static int
filt_timerattach(struct knote *kn)
@@ -566,7 +589,11 @@ filt_timerattach(struct knote *kn)
return (EINVAL);
if ((intptr_t)kn->kn_sdata == 0 && (kn->kn_flags & EV_ONESHOT) == 0)
kn->kn_sdata = 1;
- to = timer2sbintime(kn->kn_sdata);
+ /* Only precision unit are supported in flags so far */
+ if (kn->kn_sfflags & ~NOTE_TIMER_PRECMASK)
+ return (EINVAL);
+
+ to = timer2sbintime(kn->kn_sdata, kn->kn_sfflags);
if (to < 0)
return (EINVAL);
@@ -583,7 +610,7 @@ filt_timerattach(struct knote *kn)
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? */,
+ callout_reset_sbt_on(calloutp, to, 0,
filt_timerexpire, kn, PCPU_GET(cpuid), 0);
return (0);
diff --git a/sys/sys/event.h b/sys/sys/event.h
index 1f27c4d..7b0b798 100644
--- a/sys/sys/event.h
+++ b/sys/sys/event.h
@@ -133,6 +133,12 @@ struct kevent {
#define NOTE_TRACKERR 0x00000002 /* could not track child */
#define NOTE_CHILD 0x00000004 /* am a child process */
+/* additional flags for EVFILE_TIMER */
+#define NOTE_SECONDS 0x00000001 /* data is seconds */
+#define NOTE_MSECONDS 0x00000002 /* data is milliseconds */
+#define NOTE_USECONDS 0x00000004 /* data is microseconds */
+#define NOTE_NSECONDS 0x00000008 /* data is nanoseconds */
+
struct knote;
SLIST_HEAD(klist, knote);
struct kqueue;
OpenPOWER on IntegriCloud