summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_event.c
diff options
context:
space:
mode:
authorsson <sson@FreeBSD.org>2009-09-16 03:15:57 +0000
committersson <sson@FreeBSD.org>2009-09-16 03:15:57 +0000
commit297d4ab14bc244018819c2a5d501fd2cd15923d1 (patch)
treef19a2ef84c58e9cb3b4a49faedbe836458d17ab6 /sys/kern/kern_event.c
parent3e3fe69f6bc0430a9bb2153acb0c9dccbddd686c (diff)
downloadFreeBSD-src-297d4ab14bc244018819c2a5d501fd2cd15923d1.zip
FreeBSD-src-297d4ab14bc244018819c2a5d501fd2cd15923d1.tar.gz
Add optional touch event filter hooks to kevents.
The touch event filter is called when a kernel event data is possibly updated. There are two hook points. First, during a kevent() system call. Second, when an event has been triggered. Approved by: rwatson (co-mentor)
Diffstat (limited to 'sys/kern/kern_event.c')
-rw-r--r--sys/kern/kern_event.c93
1 files changed, 56 insertions, 37 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index 6336049..cf402a2 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -1,6 +1,7 @@
/*-
* Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org>
* Copyright 2004 John-Mark Gurney <jmg@FreeBSD.org>
+ * Copyright (c) 2009 Apple, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -934,17 +935,11 @@ findkn:
goto findkn;
}
- if (kn == NULL && ((kev->flags & EV_ADD) == 0)) {
- KQ_UNLOCK(kq);
- error = ENOENT;
- goto done;
- }
-
/*
* kn now contains the matching knote, or NULL if no match
*/
- if (kev->flags & EV_ADD) {
- if (kn == NULL) {
+ if (kn == NULL) {
+ if (kev->flags & EV_ADD) {
kn = tkn;
tkn = NULL;
if (kn == NULL) {
@@ -983,34 +978,16 @@ findkn:
goto done;
}
KN_LIST_LOCK(kn);
+ goto done_ev_add;
} else {
- /*
- * The user may change some filter values after the
- * initial EV_ADD, but doing so will not reset any
- * filter which has already been triggered.
- */
- kn->kn_status |= KN_INFLUX;
+ /* No matching knote and the EV_ADD flag is not set. */
KQ_UNLOCK(kq);
- KN_LIST_LOCK(kn);
- kn->kn_sfflags = kev->fflags;
- kn->kn_sdata = kev->data;
- kn->kn_kevent.udata = kev->udata;
+ error = ENOENT;
+ goto done;
}
-
- /*
- * We can get here with kn->kn_knlist == NULL.
- * This can happen when the initial attach event decides that
- * the event is "completed" already. i.e. filt_procattach
- * is called on a zombie process. It will call filt_proc
- * which will remove it from the list, and NULL kn_knlist.
- */
- event = kn->kn_fop->f_event(kn, 0);
- KQ_LOCK(kq);
- if (event)
- KNOTE_ACTIVATE(kn, 1);
- kn->kn_status &= ~KN_INFLUX;
- KN_LIST_UNLOCK(kn);
- } else if (kev->flags & EV_DELETE) {
+ }
+
+ if (kev->flags & EV_DELETE) {
kn->kn_status |= KN_INFLUX;
KQ_UNLOCK(kq);
if (!(kn->kn_status & KN_DETACHED))
@@ -1019,6 +996,37 @@ findkn:
goto done;
}
+ /*
+ * The user may change some filter values after the initial EV_ADD,
+ * but doing so will not reset any filter which has already been
+ * triggered.
+ */
+ kn->kn_status |= KN_INFLUX;
+ KQ_UNLOCK(kq);
+ KN_LIST_LOCK(kn);
+ kn->kn_kevent.udata = kev->udata;
+ if (!fops->f_isfd && fops->f_touch != NULL) {
+ fops->f_touch(kn, kev, EVENT_REGISTER);
+ } else {
+ kn->kn_sfflags = kev->fflags;
+ kn->kn_sdata = kev->data;
+ }
+
+ /*
+ * We can get here with kn->kn_knlist == NULL. This can happen when
+ * the initial attach event decides that the event is "completed"
+ * already. i.e. filt_procattach is called on a zombie process. It
+ * will call filt_proc which will remove it from the list, and NULL
+ * kn_knlist.
+ */
+done_ev_add:
+ event = kn->kn_fop->f_event(kn, 0);
+ KQ_LOCK(kq);
+ if (event)
+ KNOTE_ACTIVATE(kn, 1);
+ kn->kn_status &= ~KN_INFLUX;
+ KN_LIST_UNLOCK(kn);
+
if ((kev->flags & EV_DISABLE) &&
((kn->kn_status & KN_DISABLED) == 0)) {
kn->kn_status |= KN_DISABLED;
@@ -1198,7 +1206,7 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops,
struct timeval atv, rtv, ttv;
struct knote *kn, *marker;
int count, timeout, nkev, error, influx;
- int haskqglobal;
+ int haskqglobal, touch;
count = maxevents;
nkev = 0;
@@ -1330,12 +1338,23 @@ start:
influx = 1;
continue;
}
- *kevp = kn->kn_kevent;
+ touch = (!kn->kn_fop->f_isfd &&
+ kn->kn_fop->f_touch != NULL);
+ if (touch)
+ kn->kn_fop->f_touch(kn, kevp, EVENT_PROCESS);
+ else
+ *kevp = kn->kn_kevent;
KQ_LOCK(kq);
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
if (kn->kn_flags & EV_CLEAR) {
- kn->kn_data = 0;
- kn->kn_fflags = 0;
+ /*
+ * Manually clear knotes who weren't
+ * 'touch'ed.
+ */
+ if (touch == 0) {
+ kn->kn_data = 0;
+ kn->kn_fflags = 0;
+ }
kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE);
kq->kq_count--;
} else
OpenPOWER on IntegriCloud