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)
This commit is contained in:
parent
297d4ab14b
commit
7cb0718a03
@ -24,7 +24,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 6, 2007
|
||||
.Dd September 15, 2009
|
||||
.Dt KQUEUE 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -441,6 +441,44 @@ The link state is invalid.
|
||||
On return,
|
||||
.Va fflags
|
||||
contains the events which triggered the filter.
|
||||
.It Dv EVFILT_USER
|
||||
Establishes a user event identified by
|
||||
.Va ident
|
||||
which is not assosicated with any kernel mechanism but is triggered by
|
||||
user level code.
|
||||
The lower 24 bits of the
|
||||
.Va fflags
|
||||
may be used for user defined flags and manipulated using the following:
|
||||
.Bl -tag -width XXNOTE_FFLAGSMASK
|
||||
.It Dv NOTE_FFNOP
|
||||
Ignore the input
|
||||
.Va fflags .
|
||||
.It Dv NOTE_FFAND
|
||||
Bitwise AND
|
||||
.Va fflags .
|
||||
.It Dv NOTE_FFOR
|
||||
Bitwise OR
|
||||
.Va fflags .
|
||||
.It Dv NOTE_COPY
|
||||
Copy
|
||||
.Va fflags .
|
||||
.It Dv NOTE_FFCTRLMASK
|
||||
Control mask for
|
||||
.Va fflags .
|
||||
.It Dv NOTE_FFLAGSMASK
|
||||
User defined flag mask for
|
||||
.Va fflags .
|
||||
.El
|
||||
.Pp
|
||||
A user event is triggered for output with the following:
|
||||
.Bl -tag -width XXNOTE_FFLAGSMASK
|
||||
.It Dv NOTE_TRIGGER
|
||||
Cause the event to be triggered.
|
||||
.El
|
||||
.Pp
|
||||
On return,
|
||||
.Va fflags
|
||||
contains the users defined flags in the lower 24 bits.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -41,7 +41,8 @@
|
||||
#define EVFILT_NETDEV (-8) /* network devices */
|
||||
#define EVFILT_FS (-9) /* filesystem events */
|
||||
#define EVFILT_LIO (-10) /* attached to lio requests */
|
||||
#define EVFILT_SYSCOUNT 10
|
||||
#define EVFILT_USER (-11) /* User events */
|
||||
#define EVFILT_SYSCOUNT 11
|
||||
|
||||
#define EV_SET(kevp_, a, b, c, d, e, f) do { \
|
||||
struct kevent *kevp = (kevp_); \
|
||||
@ -79,6 +80,25 @@ struct kevent {
|
||||
#define EV_EOF 0x8000 /* EOF detected */
|
||||
#define EV_ERROR 0x4000 /* error, data contains errno */
|
||||
|
||||
/*
|
||||
* data/hint flags/masks for EVFILT_USER, shared with userspace
|
||||
*
|
||||
* On input, the top two bits of fflags specifies how the lower twenty four
|
||||
* bits should be applied to the stored value of fflags.
|
||||
*
|
||||
* On output, the top two bits will always be set to NOTE_FFNOP and the
|
||||
* remaining twenty four bits will contain the stored fflags value.
|
||||
*/
|
||||
#define NOTE_FFNOP 0x00000000 /* ignore input fflags */
|
||||
#define NOTE_FFAND 0x40000000 /* AND fflags */
|
||||
#define NOTE_FFOR 0x80000000 /* OR fflags */
|
||||
#define NOTE_FFCOPY 0xc0000000 /* copy fflags */
|
||||
#define NOTE_FFCTRLMASK 0xc0000000 /* masks for operations */
|
||||
#define NOTE_FFLAGSMASK 0x00ffffff
|
||||
|
||||
#define NOTE_TRIGGER 0x01000000 /* Cause the event to be
|
||||
triggered for output. */
|
||||
|
||||
/*
|
||||
* data/hint flags for EVFILT_{READ|WRITE}, shared with userspace
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user