diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2 --- a/lib/libc/sys/kqueue.2 +++ b/lib/libc/sys/kqueue.2 @@ -250,6 +250,21 @@ See .Sx RETURN VALUES below. +.It Dv EV_KEEPUDATA +Causes +.Fn kevent +to leave unchanged any +.Fa udata +associated with an existing event. This allows other aspects of the +event to be modified without requiring the caller to know the +.Fa udata +value presently associated. +This is especially useful with +.Dv NOTE_TRIGGER +or flags like +.Dv EV_ENABLE. +This flag may not be used with +.Dv EV_ADD. .El .Pp The predefined system filters are listed below. diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1441,6 +1441,13 @@ return EINVAL; if (kev->flags & EV_ADD) { + /* Reject an invalid flag pair early */ + if (kev->flags & EV_KEEPUDATA) { + tkn = NULL; + error = EINVAL; + goto done; + } + /* * Prevent waiting with locks. Non-sleepable * allocation failures are handled in the loop, only @@ -1629,7 +1636,8 @@ kn_enter_flux(kn); KQ_UNLOCK(kq); knl = kn_list_lock(kn); - kn->kn_kevent.udata = kev->udata; + if ((kev->flags & EV_KEEPUDATA) == 0) + kn->kn_kevent.udata = kev->udata; if (!fops->f_isfd && fops->f_touch != NULL) { fops->f_touch(kn, kev, EVENT_REGISTER); } else { diff --git a/sys/sys/event.h b/sys/sys/event.h --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -163,6 +163,7 @@ #define EV_ENABLE 0x0004 /* enable event */ #define EV_DISABLE 0x0008 /* disable event (not reported) */ #define EV_FORCEONESHOT 0x0100 /* enable _ONESHOT and force trigger */ +#define EV_KEEPUDATA 0x0200 /* do not update the udata field */ /* flags */ #define EV_ONESHOT 0x0010 /* only report one occurrence */