summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorsson <sson@FreeBSD.org>2009-09-16 03:30:12 +0000
committersson <sson@FreeBSD.org>2009-09-16 03:30:12 +0000
commit7cb0718a03501c7ac46ff447e23b5aa2a3bd3928 (patch)
tree5cf08a4d51efab9fe7faf458cadd04f32b9753d0 /sys/kern/kern_event.c
parent297d4ab14bc244018819c2a5d501fd2cd15923d1 (diff)
downloadFreeBSD-src-7cb0718a03501c7ac46ff447e23b5aa2a3bd3928.zip
FreeBSD-src-7cb0718a03501c7ac46ff447e23b5aa2a3bd3928.tar.gz
Add EVFILT_USER to kevents.
Add user events support to kernel events which are not associated with any kernel mechanism but are triggered by user level code. This is useful for adding user level events to an event handler that may also be monitoring kernel events. Approved by: rwatson (co-mentor)
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index cf402a2..92afec2 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -142,6 +142,10 @@ static void filt_timerexpire(void *knx);
static int filt_timerattach(struct knote *kn);
static void filt_timerdetach(struct knote *kn);
static int filt_timer(struct knote *kn, long hint);
+static int filt_userattach(struct knote *kn);
+static void filt_userdetach(struct knote *kn);
+static int filt_user(struct knote *kn, long hint);
+static void filt_usertouch(struct knote *kn, struct kevent *kev, long type);
static struct filterops file_filtops = {
.f_isfd = 1,
@@ -165,6 +169,12 @@ static struct filterops timer_filtops = {
.f_detach = filt_timerdetach,
.f_event = filt_timer,
};
+static struct filterops user_filtops = {
+ .f_attach = filt_userattach,
+ .f_detach = filt_userdetach,
+ .f_event = filt_user,
+ .f_touch = filt_usertouch,
+};
static uma_zone_t knote_zone;
static int kq_ncallouts = 0;
@@ -271,6 +281,7 @@ static struct {
{ &file_filtops }, /* EVFILT_NETDEV */
{ &fs_filtops }, /* EVFILT_FS */
{ &null_filtops }, /* EVFILT_LIO */
+ { &user_filtops }, /* EVFILT_USER */
};
/*
@@ -573,6 +584,94 @@ filt_timer(struct knote *kn, long hint)
return (kn->kn_data != 0);
}
+static int
+filt_userattach(struct knote *kn)
+{
+
+ /*
+ * EVFILT_USER knotes are not attached to anything in the kernel.
+ */
+ kn->kn_hook = NULL;
+ if (kn->kn_fflags & NOTE_TRIGGER)
+ kn->kn_hookid = 1;
+ else
+ kn->kn_hookid = 0;
+ return (0);
+}
+
+static void
+filt_userdetach(__unused struct knote *kn)
+{
+
+ /*
+ * EVFILT_USER knotes are not attached to anything in the kernel.
+ */
+}
+
+static int
+filt_user(struct knote *kn, __unused long hint)
+{
+
+ return (kn->kn_hookid);
+}
+
+static void
+filt_usertouch(struct knote *kn, struct kevent *kev, long type)
+{
+ int ffctrl;
+
+ switch (type) {
+ case EVENT_REGISTER:
+ if (kev->fflags & NOTE_TRIGGER)
+ kn->kn_hookid = 1;
+
+ ffctrl = kev->fflags & NOTE_FFCTRLMASK;
+ kev->fflags &= NOTE_FFLAGSMASK;
+ switch (ffctrl) {
+ case NOTE_FFNOP:
+ break;
+
+ case NOTE_FFAND:
+ kn->kn_sfflags &= kev->fflags;
+ break;
+
+ case NOTE_FFOR:
+ kn->kn_sfflags |= kev->fflags;
+ break;
+
+ case NOTE_FFCOPY:
+ kn->kn_sfflags = kev->fflags;
+ break;
+
+ default:
+ /* XXX Return error? */
+ break;
+ }
+ kn->kn_sdata = kev->data;
+ if (kev->flags & EV_CLEAR) {
+ kn->kn_hookid = 0;
+ kn->kn_data = 0;
+ kn->kn_fflags = 0;
+ }
+ break;
+
+ case EVENT_PROCESS:
+ *kev = kn->kn_kevent;
+ kev->fflags = kn->kn_sfflags;
+ kev->data = kn->kn_sdata;
+ if (kn->kn_flags & EV_CLEAR) {
+ kn->kn_hookid = 0;
+ kn->kn_data = 0;
+ kn->kn_fflags = 0;
+ }
+ break;
+
+ default:
+ panic("filt_usertouch() - invalid type (%ld)", type);
+ break;
+ }
+}
+
int
kqueue(struct thread *td, struct kqueue_args *uap)
{
OpenPOWER on IntegriCloud