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)
This commit is contained in:
parent
11c99a6d7b
commit
95128e983f
@ -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 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
|
||||
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 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
|
||||
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 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
|
||||
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 @@ kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops,
|
||||
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
|
||||
|
@ -154,11 +154,22 @@ MALLOC_DECLARE(M_KQUEUE);
|
||||
*/
|
||||
#define NOTE_SIGNAL 0x08000000
|
||||
|
||||
/*
|
||||
* Hint values for the optional f_touch event filter. If f_touch is not set
|
||||
* to NULL and f_isfd is zero the f_touch filter will be called with the type
|
||||
* argument set to EVENT_REGISTER during a kevent() system call. It is also
|
||||
* called under the same conditions with the type argument set to EVENT_PROCESS
|
||||
* when the event has been triggered.
|
||||
*/
|
||||
#define EVENT_REGISTER 1
|
||||
#define EVENT_PROCESS 2
|
||||
|
||||
struct filterops {
|
||||
int f_isfd; /* true if ident == filedescriptor */
|
||||
int (*f_attach)(struct knote *kn);
|
||||
void (*f_detach)(struct knote *kn);
|
||||
int (*f_event)(struct knote *kn, long hint);
|
||||
void (*f_touch)(struct knote *kn, struct kevent *kev, long type);
|
||||
};
|
||||
|
||||
/*
|
||||
@ -193,6 +204,7 @@ struct knote {
|
||||
} kn_ptr;
|
||||
struct filterops *kn_fop;
|
||||
void *kn_hook;
|
||||
int kn_hookid;
|
||||
|
||||
#define kn_id kn_kevent.ident
|
||||
#define kn_filter kn_kevent.filter
|
||||
|
Loading…
Reference in New Issue
Block a user