Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_event.c
Show First 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | |||||
static void kqueue_drain(struct kqueue *kq, struct thread *td); | static void kqueue_drain(struct kqueue *kq, struct thread *td); | ||||
static int kqueue_expand(struct kqueue *kq, struct filterops *fops, | static int kqueue_expand(struct kqueue *kq, struct filterops *fops, | ||||
uintptr_t ident, int mflag); | uintptr_t ident, int mflag); | ||||
static void kqueue_task(void *arg, int pending); | static void kqueue_task(void *arg, int pending); | ||||
static int kqueue_scan(struct kqueue *kq, int maxevents, | static int kqueue_scan(struct kqueue *kq, int maxevents, | ||||
struct kevent_copyops *k_ops, | struct kevent_copyops *k_ops, | ||||
const struct timespec *timeout, | const struct timespec *timeout, | ||||
struct kevent *keva, struct thread *td); | struct kevent *keva, struct thread *td); | ||||
static void kqueue_wakeup(struct kqueue *kq); | static void kqueue_wakeup(struct kqueue *kq, bool one); | ||||
static struct filterops *kqueue_fo_find(int filt); | static struct filterops *kqueue_fo_find(int filt); | ||||
static void kqueue_fo_release(int filt); | static void kqueue_fo_release(int filt); | ||||
struct g_kevent_args; | struct g_kevent_args; | ||||
static int kern_kevent_generic(struct thread *td, | static int kern_kevent_generic(struct thread *td, | ||||
struct g_kevent_args *uap, | struct g_kevent_args *uap, | ||||
struct kevent_copyops *k_ops, const char *struct_name); | struct kevent_copyops *k_ops, const char *struct_name); | ||||
static fo_ioctl_t kqueue_ioctl; | static fo_ioctl_t kqueue_ioctl; | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | #define KNOTE_ACTIVATE(kn, islock) do { \ | ||||
else \ | else \ | ||||
KQ_LOCK((kn)->kn_kq); \ | KQ_LOCK((kn)->kn_kq); \ | ||||
(kn)->kn_status |= KN_ACTIVE; \ | (kn)->kn_status |= KN_ACTIVE; \ | ||||
if (((kn)->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) \ | if (((kn)->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) \ | ||||
knote_enqueue((kn)); \ | knote_enqueue((kn)); \ | ||||
if (!(islock)) \ | if (!(islock)) \ | ||||
KQ_UNLOCK((kn)->kn_kq); \ | KQ_UNLOCK((kn)->kn_kq); \ | ||||
} while (0) | } while (0) | ||||
#define KNOTE_ACTIVATE2(kn, islock, isbreak) do { \ | |||||
if ((islock)) \ | |||||
mtx_assert(&(kn)->kn_kq->kq_lock, MA_OWNED); \ | |||||
else \ | |||||
KQ_LOCK((kn)->kn_kq); \ | |||||
(kn)->kn_status |= KN_ACTIVE; \ | |||||
(isbreak) = ((kn->kn_flags & EV_EXCLUSIVE) != 0); \ | |||||
if (((kn)->kn_status & (KN_QUEUED | KN_DISABLED)) == 0) \ | |||||
knote_enqueue((kn)); \ | |||||
if (!(islock)) \ | |||||
KQ_UNLOCK((kn)->kn_kq); \ | |||||
} while (0) | |||||
#define KQ_LOCK(kq) do { \ | #define KQ_LOCK(kq) do { \ | ||||
mtx_lock(&(kq)->kq_lock); \ | mtx_lock(&(kq)->kq_lock); \ | ||||
} while (0) | } while (0) | ||||
#define KQ_FLUX_WAKEUP(kq) do { \ | #define KQ_FLUX_WAKEUP(kq) do { \ | ||||
if (((kq)->kq_state & KQ_FLUXWAIT) == KQ_FLUXWAIT) { \ | if (((kq)->kq_state & KQ_FLUXWAIT) == KQ_FLUXWAIT) { \ | ||||
(kq)->kq_state &= ~KQ_FLUXWAIT; \ | (kq)->kq_state &= ~KQ_FLUXWAIT; \ | ||||
wakeup((kq)); \ | wakeup((kq)); \ | ||||
} \ | } \ | ||||
▲ Show 20 Lines • Show All 1,832 Lines • ▼ Show 20 Lines | if ((kn->kn_flags & EV_DROP) == EV_DROP) { | ||||
if (touch == 0 && kn->kn_flags & EV_CLEAR) { | if (touch == 0 && kn->kn_flags & EV_CLEAR) { | ||||
kn->kn_data = 0; | kn->kn_data = 0; | ||||
kn->kn_fflags = 0; | kn->kn_fflags = 0; | ||||
} | } | ||||
if (kn->kn_flags & EV_DISPATCH) | if (kn->kn_flags & EV_DISPATCH) | ||||
kn->kn_status |= KN_DISABLED; | kn->kn_status |= KN_DISABLED; | ||||
kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE); | kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE); | ||||
kq->kq_count--; | kq->kq_count--; | ||||
} else | } else | ||||
markj: There is no need to add a separate case, you can change line 2061 to `if ((kn->kn_flags &… | |||||
TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); | TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); | ||||
kn->kn_status &= ~KN_SCAN; | kn->kn_status &= ~KN_SCAN; | ||||
kn_leave_flux(kn); | kn_leave_flux(kn); | ||||
kn_list_unlock(knl); | kn_list_unlock(knl); | ||||
influx = 1; | influx = 1; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 242 Lines • ▼ Show 20 Lines | |||||
kqueue_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) | kqueue_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp) | ||||
{ | { | ||||
kif->kf_type = KF_TYPE_KQUEUE; | kif->kf_type = KF_TYPE_KQUEUE; | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static void | ||||
kqueue_wakeup(struct kqueue *kq) | kqueue_wakeup(struct kqueue *kq, bool one) | ||||
{ | { | ||||
KQ_OWNED(kq); | KQ_OWNED(kq); | ||||
if ((kq->kq_state & KQ_SLEEP) == KQ_SLEEP) { | if ((kq->kq_state & KQ_SLEEP) == KQ_SLEEP) { | ||||
kq->kq_state &= ~KQ_SLEEP; | kq->kq_state &= ~KQ_SLEEP; | ||||
wakeup(kq); | one == true ? wakeup_one(kq) : wakeup(kq); | ||||
} | } | ||||
if ((kq->kq_state & KQ_SEL) == KQ_SEL) { | if ((kq->kq_state & KQ_SEL) == KQ_SEL) { | ||||
selwakeuppri(&kq->kq_sel, PSOCK); | selwakeuppri(&kq->kq_sel, PSOCK); | ||||
if (!SEL_WAITING(&kq->kq_sel)) | if (!SEL_WAITING(&kq->kq_sel)) | ||||
kq->kq_state &= ~KQ_SEL; | kq->kq_state &= ~KQ_SEL; | ||||
} | } | ||||
if (!knlist_empty(&kq->kq_sel.si_note)) | if (!knlist_empty(&kq->kq_sel.si_note)) | ||||
kqueue_schedtask(kq); | kqueue_schedtask(kq); | ||||
Show All 10 Lines | |||||
* down the chain to make up the parent kqueue. Make this code functional | * down the chain to make up the parent kqueue. Make this code functional | ||||
* first. | * first. | ||||
*/ | */ | ||||
void | void | ||||
knote(struct knlist *list, long hint, int lockflags) | knote(struct knlist *list, long hint, int lockflags) | ||||
{ | { | ||||
struct kqueue *kq; | struct kqueue *kq; | ||||
struct knote *kn, *tkn; | struct knote *kn, *tkn; | ||||
int error; | int error, stop; | ||||
if (list == NULL) | if (list == NULL) | ||||
return; | return; | ||||
KNL_ASSERT_LOCK(list, lockflags & KNF_LISTLOCKED); | KNL_ASSERT_LOCK(list, lockflags & KNF_LISTLOCKED); | ||||
if ((lockflags & KNF_LISTLOCKED) == 0) | if ((lockflags & KNF_LISTLOCKED) == 0) | ||||
list->kl_lock(list->kl_lockarg); | list->kl_lock(list->kl_lockarg); | ||||
Show All 20 Lines | if (kn_in_flux(kn) && (kn->kn_status & KN_SCAN) == 0) { | ||||
KQ_UNLOCK(kq); | KQ_UNLOCK(kq); | ||||
} else if ((lockflags & KNF_NOKQLOCK) != 0) { | } else if ((lockflags & KNF_NOKQLOCK) != 0) { | ||||
kn_enter_flux(kn); | kn_enter_flux(kn); | ||||
KQ_UNLOCK(kq); | KQ_UNLOCK(kq); | ||||
error = kn->kn_fop->f_event(kn, hint); | error = kn->kn_fop->f_event(kn, hint); | ||||
KQ_LOCK(kq); | KQ_LOCK(kq); | ||||
kn_leave_flux(kn); | kn_leave_flux(kn); | ||||
if (error) | if (error) | ||||
KNOTE_ACTIVATE(kn, 1); | KNOTE_ACTIVATE2(kn, 1, stop); | ||||
KQ_UNLOCK_FLUX(kq); | KQ_UNLOCK_FLUX(kq); | ||||
} else { | } else { | ||||
if (kn->kn_fop->f_event(kn, hint)) | if (kn->kn_fop->f_event(kn, hint)) | ||||
KNOTE_ACTIVATE(kn, 1); | KNOTE_ACTIVATE2(kn, 1, stop); | ||||
KQ_UNLOCK(kq); | KQ_UNLOCK(kq); | ||||
} | } | ||||
if (stop) | |||||
break; | |||||
} | } | ||||
if ((lockflags & KNF_LISTLOCKED) == 0) | if ((lockflags & KNF_LISTLOCKED) == 0) | ||||
list->kl_unlock(list->kl_lockarg); | list->kl_unlock(list->kl_lockarg); | ||||
} | } | ||||
/* | /* | ||||
* add a knote to a knlist | * add a knote to a knlist | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 357 Lines • ▼ Show 20 Lines | knote_drop_detached(struct knote *kn, struct thread *td) | ||||
kn->kn_fop = NULL; | kn->kn_fop = NULL; | ||||
knote_free(kn); | knote_free(kn); | ||||
} | } | ||||
static void | static void | ||||
knote_enqueue(struct knote *kn) | knote_enqueue(struct knote *kn) | ||||
{ | { | ||||
struct kqueue *kq = kn->kn_kq; | struct kqueue *kq = kn->kn_kq; | ||||
bool one; | |||||
KQ_OWNED(kn->kn_kq); | KQ_OWNED(kn->kn_kq); | ||||
KASSERT((kn->kn_status & KN_QUEUED) == 0, ("knote already queued")); | KASSERT((kn->kn_status & KN_QUEUED) == 0, ("knote already queued")); | ||||
TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); | TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe); | ||||
kn->kn_status |= KN_QUEUED; | kn->kn_status |= KN_QUEUED; | ||||
kq->kq_count++; | kq->kq_count++; | ||||
kqueue_wakeup(kq); | one = (kn->kn_flags & EV_EXCLUSIVE) != 0; | ||||
kqueue_wakeup(kq, one); | |||||
} | } | ||||
static void | static void | ||||
knote_dequeue(struct knote *kn) | knote_dequeue(struct knote *kn) | ||||
{ | { | ||||
struct kqueue *kq = kn->kn_kq; | struct kqueue *kq = kn->kn_kq; | ||||
KQ_OWNED(kn->kn_kq); | KQ_OWNED(kn->kn_kq); | ||||
▲ Show 20 Lines • Show All 55 Lines • Show Last 20 Lines |
There is no need to add a separate case, you can change line 2061 to if ((kn->kn_flags & EV_CLEAR | EV_DISPATCH | EV_EXCLUSIVE)) != 0) { and the behaviour will be unchanged.