2 * Copyright (c) 2009 Mark Heily <mark@heily.com>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 #include <sys/queue.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
30 #include "sys/event.h"
35 itimerspec_dump(struct itimerspec *ts)
37 static char __thread buf[1024];
39 snprintf(buf, sizeof(buf),
40 "itimer: [ interval=%lu s %lu ns, next expire=%lu s %lu ns ]",
41 ts->it_interval.tv_sec,
42 ts->it_interval.tv_nsec,
51 /* Convert milliseconds into seconds+nanoseconds */
53 convert_msec_to_itimerspec(struct itimerspec *dst, int src, int oneshot)
58 nsec = (src % 1000) * 1000000;
60 /* Set the interval */
62 dst->it_interval.tv_sec = 0;
63 dst->it_interval.tv_nsec = 0;
65 dst->it_interval.tv_sec = sec;
66 dst->it_interval.tv_nsec = nsec;
69 /* Set the initial expiration */
70 dst->it_value.tv_sec = sec;
71 dst->it_value.tv_nsec = nsec;
72 dbg_printf("%s", itimerspec_dump(dst));
76 ktimer_create(struct filter *filt, struct knote *kn)
83 kn->kev.flags |= EV_CLEAR;
85 pn.portnfy_port = filt->kf_kqueue->kq_port;
86 pn.portnfy_user = (void *) kn->kev.ident;
88 se.sigev_notify = SIGEV_PORT;
89 se.sigev_value.sival_ptr = &pn;
91 if (timer_create (CLOCK_MONOTONIC, &se, &timerid) < 0) {
92 dbg_perror("timer_create(2)");
96 convert_msec_to_itimerspec(&ts, kn->kev.data, kn->kev.flags & EV_ONESHOT);
97 if (timer_settime(timerid, 0, &ts, NULL) < 0) {
98 dbg_perror("timer_settime(2)");
99 (void) timer_delete(timerid);
103 kn->data.timerid = timerid;
104 dbg_printf("created timer with id #%lu", (unsigned long) timerid);
110 evfilt_timer_init(struct filter *filt)
116 evfilt_timer_destroy(struct filter *filt)
122 evfilt_timer_copyout(struct filter *filt,
126 port_event_t *pe = (port_event_t *) pthread_getspecific(filt->kf_kqueue->kq_port_event);
131 /* XXX-FIXME: danger here -- there has to be a better way */
132 buf = (long) pe->portev_user;
133 timerid = (timer_t) buf;
135 kn = knote_lookup(filt, timerid);
137 dbg_printf("knote=%p", kn);
138 memcpy(dst, &kn->kev, sizeof(*dst));
140 //if (ev->events & EPOLLERR)
141 // dst->fflags = 1; /* FIXME: Return the actual timer error */
143 /* FIXME: On return, data contains the number of times the
144 timer has been trigered.
146 dst->data = 1; //workaround
148 if (kn->kev.flags & EV_DISPATCH) {
150 timer_delete(kn->data.timerid);
151 } else if (kn->kev.flags & EV_ONESHOT) {
152 timer_delete(kn->data.timerid);
153 knote_free(filt, kn);
160 evfilt_timer_knote_create(struct filter *filt, struct knote *kn)
162 return ktimer_create(filt, kn);
166 evfilt_timer_knote_modify(struct filter *filt, struct knote *kn,
167 const struct kevent *kev)
169 return (-1); /* STUB */
173 evfilt_timer_knote_delete(struct filter *filt, struct knote *kn)
175 if (kn->kev.flags & EV_DISABLE)
178 dbg_printf("deleting timer # %d", kn->data.timerid);
179 return timer_delete(kn->data.timerid);
183 evfilt_timer_knote_enable(struct filter *filt, struct knote *kn)
185 return evfilt_timer_knote_create(filt, kn);
189 evfilt_timer_knote_disable(struct filter *filt, struct knote *kn)
191 return evfilt_timer_knote_delete(filt, kn);
194 const struct filter evfilt_timer = {
197 evfilt_timer_destroy,
198 evfilt_timer_copyout,
199 evfilt_timer_knote_create,
200 evfilt_timer_knote_modify,
201 evfilt_timer_knote_delete,
202 evfilt_timer_knote_enable,
203 evfilt_timer_knote_disable,