From a90788cb44227a1618bc7341cd179c115047ab13 Mon Sep 17 00:00:00 2001 From: Hubertus Franke Date: Wed, 29 Jun 2016 17:29:15 -0400 Subject: [PATCH] support for kevent type timer resolutions add documentation for timer resolution --- include/sys/event.h | 9 +++++++++ kqueue.2 | 16 +++++++++++++++- src/linux/timer.c | 34 ++++++++++++++++++++++++++++------ 3 files changed, 52 insertions(+), 7 deletions(-) diff --git a/include/sys/event.h b/include/sys/event.h index 610ab449..087917df 100644 --- a/include/sys/event.h +++ b/include/sys/event.h @@ -168,6 +168,15 @@ struct kevent { program */ #define VQ_NOTRESPLOCK 0x0080 /* server lockd down */ +/* + * data/hint flags for EVFILT_TIMER as suported and defined in kevent64 + */ +#define NOTE_SECONDS 0x0001 /* time specified in seconds */ +#define NOTE_USECONDS 0x0002 /* time specified in micro seconds */ +#define NOTE_NSECONDS 0x0004 /* time specified in nano seconds */ +#define NOTE_ABSOLUTE 0x0008 /* data is an absolute timeout */ + + #ifndef __KERNEL__ #ifdef __cplusplus diff --git a/kqueue.2 b/kqueue.2 index 22cca6cc..d8b5414f 100644 --- a/kqueue.2 +++ b/kqueue.2 @@ -364,7 +364,21 @@ Establishes an arbitrary timer identified by .Va ident . When adding a timer, .Va data -specifies the timeout period in milliseconds. +specifies the timeout period and +.Va fflags +can be set to one of the following: +.Bl -tag -width XXNOTE_RENAME +.It NOTE_SECONDS +data is in seconds +.It NOTE_USECONDS +data is in microseconds +.It NOTE_NSECONDS +data is in nanoseconds +.It NOTE_ABSOLUTE +data is an absolute timeout +.El +.Pp +If fflags is not set, the default is milliseconds. The timer will be periodic unless EV_ONESHOT is specified. On return, .Va data diff --git a/src/linux/timer.c b/src/linux/timer.c index 7cd48c5d..06ddfc8b 100644 --- a/src/linux/timer.c +++ b/src/linux/timer.c @@ -79,14 +79,33 @@ itimerspec_dump(struct itimerspec *ts) } #endif -/* Convert milliseconds into seconds+nanoseconds */ +/* Convert time data into seconds+nanoseconds */ + +#define NOTE_TIMER_MASK (NOTE_ABSOLUTE-1) + static void -convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot) +convert_timedata_to_itimerspec(struct itimerspec *dst, long src, + unsigned int flags, int oneshot) { time_t sec, nsec; - sec = src / 1000; - nsec = (src % 1000) * 1000000; + switch (flags & NOTE_TIMER_MASK) { + case NOTE_USECONDS: + sec = src / 1000000; + nsec = (src % 1000000); + break; + case NOTE_NSECONDS: + sec = src / 1000000000; + nsec = (src % 1000000000); + break; + case NOTE_SECONDS: + sec = src; + nsec = 0; + break; + default: /* milliseconds */ + sec = src / 1000; + nsec = (src % 1000) * 1000000; + } /* Set the interval */ if (oneshot) { @@ -133,6 +152,7 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) struct epoll_event ev; struct itimerspec ts; int tfd; + int flags; kn->kev.flags |= EV_CLEAR; @@ -143,8 +163,10 @@ evfilt_timer_knote_create(struct filter *filt, struct knote *kn) } dbg_printf("created timerfd %d", tfd); - convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT); - if (timerfd_settime(tfd, 0, &ts, NULL) < 0) { + convert_timedata_to_itimerspec(&ts, kn->kev.data, kn->kev.fflags, + kn->kev.flags & EV_ONESHOT); + flags = (kn->kev.fflags & NOTE_ABSOLUTE) ? TFD_TIMER_ABSTIME : 0; + if (timerfd_settime(tfd, flags, &ts, NULL) < 0) { dbg_printf("timerfd_settime(2): %s", strerror(errno)); close(tfd); return (-1);