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>
29 #include "sys/event.h"
33 evfilt_user_init(struct filter *filt)
35 filt->kf_efd = eventfd_create();
36 if (filt->kf_efd == NULL)
39 filt->kf_pfd = eventfd_reader(filt->kf_efd);
47 evfilt_user_destroy(struct filter *filt)
49 eventfd_free(filt->kf_efd);
54 evfilt_user_copyout(struct filter *filt,
61 for (kn = knote_dequeue(filt); kn != NULL; kn = knote_dequeue(filt)) {
62 memcpy(dst, &kn->kev, sizeof(*dst));
63 dst->fflags &= ~NOTE_FFCTRLMASK; //FIXME: Not sure if needed
64 dst->fflags &= ~NOTE_TRIGGER;
65 if (kn->kev.flags & EV_ADD) {
66 /* NOTE: True on FreeBSD but not consistent behavior with
68 dst->flags &= ~EV_ADD;
70 if (kn->kev.flags & EV_CLEAR)
71 kn->kev.fflags &= ~NOTE_TRIGGER;
72 if (kn->kev.flags & (EV_DISPATCH | EV_CLEAR | EV_ONESHOT))
73 eventfd_lower(filt->kf_efd);
74 if (kn->kev.flags & EV_DISPATCH) {
76 kn->kev.fflags &= ~NOTE_TRIGGER;
77 } else if (kn->kev.flags & EV_ONESHOT) {
82 if (++nevents == maxevents)
86 /* This should normally never happen but is here for debugging */
88 dbg_puts("spurious wakeup");
89 eventfd_lower(filt->kf_efd);
96 evfilt_user_knote_create(struct filter *filt, struct knote *kn)
101 //determine if EV_ADD + NOTE_TRIGGER in the same kevent will cause a trigger */
102 if ((!(dst->kev.flags & EV_DISABLE)) && src->fflags & NOTE_TRIGGER) {
103 dst->kev.fflags |= NOTE_TRIGGER;
104 eventfd_raise(filt->kf_pfd);
112 evfilt_user_knote_modify(struct filter *filt, struct knote *kn,
113 const struct kevent *kev)
118 /* Excerpted from sys/kern/kern_event.c in FreeBSD HEAD */
119 ffctrl = kev->fflags & NOTE_FFCTRLMASK;
120 fflags = kev->fflags & NOTE_FFLAGSMASK;
126 kn->kev.fflags &= fflags;
130 kn->kev.fflags |= fflags;
134 kn->kev.fflags = fflags;
138 /* XXX Return error? */
142 if ((!(kn->kev.flags & EV_DISABLE)) && kev->fflags & NOTE_TRIGGER) {
143 kn->kev.fflags |= NOTE_TRIGGER;
144 knote_enqueue(filt, kn);
145 eventfd_raise(filt->kf_efd);
152 evfilt_user_knote_delete(struct filter *filt, struct knote *kn)
158 evfilt_user_knote_enable(struct filter *filt, struct knote *kn)
160 /* FIXME: what happens if NOTE_TRIGGER is in fflags?
161 should the event fire? */
166 evfilt_user_knote_disable(struct filter *filt, struct knote *kn)
171 const struct filter evfilt_user = {
176 evfilt_user_knote_create,
177 evfilt_user_knote_modify,
178 evfilt_user_knote_delete,
179 evfilt_user_knote_enable,
180 evfilt_user_knote_disable,