MFC r268843 (by bapt):

Extend kqueue's EVFILT_TIMER by adding precision unit flags support.
This commit is contained in:
kib 2014-12-18 11:30:51 +00:00
parent 3abf5d53d8
commit 9f63b4b4d8
3 changed files with 61 additions and 10 deletions

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd January 21, 2013
.Dd July 18, 2014
.Dt KQUEUE 2
.Os
.Sh NAME
@ -436,7 +436,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
@ -447,8 +447,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

View File

@ -522,15 +522,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 > INT64_MAX / SBT_1MS)
return INT64_MAX;
if (data > SBT_MAX / modifier)
return (SBT_MAX);
#endif
return (SBT_1MS * data);
return (modifier * data);
}
static void
@ -545,14 +568,15 @@ filt_timerexpire(void *knx)
if ((kn->kn_flags & EV_ONESHOT) != EV_ONESHOT) {
calloutp = (struct callout *)kn->kn_hook;
*kn->kn_ptr.p_nexttime += timer2sbintime(kn->kn_sdata);
*kn->kn_ptr.p_nexttime += timer2sbintime(kn->kn_sdata,
kn->kn_sfflags);
callout_reset_sbt_on(calloutp, *kn->kn_ptr.p_nexttime, 0,
filt_timerexpire, kn, PCPU_GET(cpuid), C_ABSOLUTE);
}
}
/*
* data contains amount of time to sleep, in milliseconds
* data contains amount of time to sleep
*/
static int
filt_timerattach(struct knote *kn)
@ -565,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);

View File

@ -132,6 +132,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;