Skip to content

Commit

Permalink
Merge pull request #14 from frankeh/timerresolution
Browse files Browse the repository at this point in the history
support for kevent64 type timer resolutions
  • Loading branch information
mheily authored Jul 20, 2016
2 parents f4f39d6 + a90788c commit b9e0152
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 7 deletions.
9 changes: 9 additions & 0 deletions include/sys/event.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 15 additions & 1 deletion kqueue.2
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 28 additions & 6 deletions src/linux/timer.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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;

Expand All @@ -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);
Expand Down

0 comments on commit b9e0152

Please sign in to comment.