Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148008811
D8898.id23284.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D8898.id23284.diff
View Options
Index: head/sys/kern/kern_event.c
===================================================================
--- head/sys/kern/kern_event.c
+++ head/sys/kern/kern_event.c
@@ -193,7 +193,7 @@
SYSCTL_UINT(_kern, OID_AUTO, kq_calloutmax, CTLFLAG_RW,
&kq_calloutmax, 0, "Maximum number of callouts allocated for kqueue");
-/* XXX - ensure not KN_INFLUX?? */
+/* XXX - ensure not influx ? */
#define KNOTE_ACTIVATE(kn, islock) do { \
if ((islock)) \
mtx_assert(&(kn)->kn_kq->kq_lock, MA_OWNED); \
@@ -254,6 +254,32 @@
}
}
+static bool
+kn_in_flux(struct knote *kn)
+{
+
+ return (kn->kn_influx > 0);
+}
+
+static void
+kn_enter_flux(struct knote *kn)
+{
+
+ KQ_OWNED(kn->kn_kq);
+ MPASS(kn->kn_influx < INT_MAX);
+ kn->kn_influx++;
+}
+
+static bool
+kn_leave_flux(struct knote *kn)
+{
+
+ KQ_OWNED(kn->kn_kq);
+ MPASS(kn->kn_influx > 0);
+ kn->kn_influx--;
+ return (kn->kn_influx == 0);
+}
+
#define KNL_ASSERT_LOCK(knl, islocked) do { \
if (islocked) \
KNL_ASSERT_LOCKED(knl); \
@@ -498,7 +524,7 @@
SLIST_FOREACH(kn, &list->kl_list, kn_selnext) {
kq = kn->kn_kq;
KQ_LOCK(kq);
- if ((kn->kn_status & (KN_INFLUX | KN_SCAN)) == KN_INFLUX) {
+ if (kn_in_flux(kn) && (kn->kn_status & KN_SCAN) == 0) {
KQ_UNLOCK(kq);
continue;
}
@@ -521,7 +547,7 @@
* track the child. Drop the locks in preparation for
* the call to kqueue_register().
*/
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
list->kl_unlock(list->kl_lockarg);
@@ -561,7 +587,7 @@
if (kn->kn_fop->f_event(kn, NOTE_FORK))
KNOTE_ACTIVATE(kn, 0);
KQ_LOCK(kq);
- kn->kn_status &= ~KN_INFLUX;
+ kn_leave_flux(kn);
KQ_UNLOCK_FLUX(kq);
list->kl_lock(list->kl_lockarg);
}
@@ -1262,7 +1288,7 @@
}
/* knote is in the process of changing, wait for it to stabilize. */
- if (kn != NULL && (kn->kn_status & KN_INFLUX) == KN_INFLUX) {
+ if (kn != NULL && kn_in_flux(kn)) {
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
if (filedesc_unlock) {
FILEDESC_XUNLOCK(td->td_proc->p_fd);
@@ -1306,7 +1332,8 @@
kn->kn_kevent = *kev;
kn->kn_kevent.flags &= ~(EV_ADD | EV_DELETE |
EV_ENABLE | EV_DISABLE | EV_FORCEONESHOT);
- kn->kn_status = KN_INFLUX|KN_DETACHED;
+ kn->kn_status = KN_DETACHED;
+ kn_enter_flux(kn);
error = knote_attach(kn, kq);
KQ_UNLOCK(kq);
@@ -1330,7 +1357,7 @@
}
if (kev->flags & EV_DELETE) {
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
if (!(kn->kn_status & KN_DETACHED))
kn->kn_fop->f_detach(kn);
@@ -1348,7 +1375,8 @@
* but doing so will not reset any filter which has already been
* triggered.
*/
- kn->kn_status |= KN_INFLUX | KN_SCAN;
+ kn->kn_status |= KN_SCAN;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
knl = kn_list_lock(kn);
kn->kn_kevent.udata = kev->udata;
@@ -1383,7 +1411,8 @@
if ((kn->kn_status & (KN_ACTIVE | KN_DISABLED | KN_QUEUED)) ==
KN_ACTIVE)
knote_enqueue(kn);
- kn->kn_status &= ~(KN_INFLUX | KN_SCAN);
+ kn->kn_status &= ~KN_SCAN;
+ kn_leave_flux(kn);
kn_list_unlock(knl);
KQ_UNLOCK_FLUX(kq);
@@ -1546,7 +1575,7 @@
/*
* Scan, update kn_data (if not ONESHOT), and copyout triggered events.
- * We treat KN_MARKER knotes as if they are INFLUX.
+ * We treat KN_MARKER knotes as if they are in flux.
*/
static int
kqueue_scan(struct kqueue *kq, int maxevents, struct kevent_copyops *k_ops,
@@ -1620,7 +1649,7 @@
kn = TAILQ_FIRST(&kq->kq_head);
if ((kn->kn_status == KN_MARKER && kn != marker) ||
- (kn->kn_status & KN_INFLUX) == KN_INFLUX) {
+ kn_in_flux(kn)) {
if (influx) {
influx = 0;
KQ_FLUX_WAKEUP(kq);
@@ -1643,17 +1672,17 @@
goto retry;
goto done;
}
- KASSERT((kn->kn_status & KN_INFLUX) == 0,
- ("KN_INFLUX set when not suppose to be"));
+ KASSERT(!kn_in_flux(kn),
+ ("knote %p is unexpectedly in flux", kn));
if ((kn->kn_flags & EV_DROP) == EV_DROP) {
kn->kn_status &= ~KN_QUEUED;
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
kq->kq_count--;
KQ_UNLOCK(kq);
/*
- * We don't need to lock the list since we've marked
- * it _INFLUX.
+ * We don't need to lock the list since we've
+ * marked it as in flux.
*/
if (!(kn->kn_status & KN_DETACHED))
kn->kn_fop->f_detach(kn);
@@ -1662,12 +1691,12 @@
continue;
} else if ((kn->kn_flags & EV_ONESHOT) == EV_ONESHOT) {
kn->kn_status &= ~KN_QUEUED;
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
kq->kq_count--;
KQ_UNLOCK(kq);
/*
- * We don't need to lock the list since we've marked
- * it _INFLUX.
+ * We don't need to lock the list since we've
+ * marked the knote as being in flux.
*/
*kevp = kn->kn_kevent;
if (!(kn->kn_status & KN_DETACHED))
@@ -1676,7 +1705,8 @@
KQ_LOCK(kq);
kn = NULL;
} else {
- kn->kn_status |= KN_INFLUX | KN_SCAN;
+ kn->kn_status |= KN_SCAN;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
if ((kn->kn_status & KN_KQUEUE) == KN_KQUEUE)
KQ_GLOBAL_LOCK(&kq_global, haskqglobal);
@@ -1684,9 +1714,9 @@
if (kn->kn_fop->f_event(kn, 0) == 0) {
KQ_LOCK(kq);
KQ_GLOBAL_UNLOCK(&kq_global, haskqglobal);
- kn->kn_status &=
- ~(KN_QUEUED | KN_ACTIVE | KN_INFLUX |
+ kn->kn_status &= ~(KN_QUEUED | KN_ACTIVE |
KN_SCAN);
+ kn_leave_flux(kn);
kq->kq_count--;
kn_list_unlock(knl);
influx = 1;
@@ -1716,7 +1746,8 @@
} else
TAILQ_INSERT_TAIL(&kq->kq_head, kn, kn_tqe);
- kn->kn_status &= ~(KN_INFLUX | KN_SCAN);
+ kn->kn_status &= ~KN_SCAN;
+ kn_leave_flux(kn);
kn_list_unlock(knl);
influx = 1;
}
@@ -1864,12 +1895,12 @@
for (i = 0; i < kq->kq_knlistsize; i++) {
while ((kn = SLIST_FIRST(&kq->kq_knlist[i])) != NULL) {
- if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) {
+ if (kn_in_flux(kn)) {
kq->kq_state |= KQ_FLUXWAIT;
msleep(kq, &kq->kq_lock, PSOCK, "kqclo1", 0);
continue;
}
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
if (!(kn->kn_status & KN_DETACHED))
kn->kn_fop->f_detach(kn);
@@ -1880,13 +1911,13 @@
if (kq->kq_knhashmask != 0) {
for (i = 0; i <= kq->kq_knhashmask; i++) {
while ((kn = SLIST_FIRST(&kq->kq_knhash[i])) != NULL) {
- if ((kn->kn_status & KN_INFLUX) == KN_INFLUX) {
+ if (kn_in_flux(kn)) {
kq->kq_state |= KQ_FLUXWAIT;
msleep(kq, &kq->kq_lock, PSOCK,
"kqclo2", 0);
continue;
}
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
if (!(kn->kn_status & KN_DETACHED))
kn->kn_fop->f_detach(kn);
@@ -2010,7 +2041,6 @@
struct kqueue *kq;
struct knote *kn, *tkn;
int error;
- bool own_influx;
if (list == NULL)
return;
@@ -2021,7 +2051,7 @@
list->kl_lock(list->kl_lockarg);
/*
- * If we unlock the list lock (and set KN_INFLUX), we can
+ * If we unlock the list lock (and enter influx), we can
* eliminate the kqueue scheduling, but this will introduce
* four lock/unlock's for each knote to test. Also, marker
* would be needed to keep iteration position, since filters
@@ -2030,7 +2060,7 @@
SLIST_FOREACH_SAFE(kn, &list->kl_list, kn_selnext, tkn) {
kq = kn->kn_kq;
KQ_LOCK(kq);
- if ((kn->kn_status & (KN_INFLUX | KN_SCAN)) == KN_INFLUX) {
+ if (kn_in_flux(kn) && (kn->kn_status & KN_SCAN) == 0) {
/*
* Do not process the influx notes, except for
* the influx coming from the kq unlock in the
@@ -2041,14 +2071,11 @@
*/
KQ_UNLOCK(kq);
} else if ((lockflags & KNF_NOKQLOCK) != 0) {
- own_influx = (kn->kn_status & KN_INFLUX) == 0;
- if (own_influx)
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
error = kn->kn_fop->f_event(kn, hint);
KQ_LOCK(kq);
- if (own_influx)
- kn->kn_status &= ~KN_INFLUX;
+ kn_leave_flux(kn);
if (error)
KNOTE_ACTIVATE(kn, 1);
KQ_UNLOCK_FLUX(kq);
@@ -2070,10 +2097,12 @@
void
knlist_add(struct knlist *knl, struct knote *kn, int islocked)
{
+
KNL_ASSERT_LOCK(knl, islocked);
KQ_NOTOWNED(kn->kn_kq);
- KASSERT((kn->kn_status & (KN_INFLUX|KN_DETACHED)) ==
- (KN_INFLUX|KN_DETACHED), ("knote not KN_INFLUX and KN_DETACHED"));
+ KASSERT(kn_in_flux(kn), ("knote %p not in flux", kn));
+ KASSERT((kn->kn_status & KN_DETACHED) != 0,
+ ("knote %p was not detached", kn));
if (!islocked)
knl->kl_lock(knl->kl_lockarg);
SLIST_INSERT_HEAD(&knl->kl_list, kn, kn_selnext);
@@ -2089,12 +2118,13 @@
knlist_remove_kq(struct knlist *knl, struct knote *kn, int knlislocked,
int kqislocked)
{
- KASSERT(!(!!kqislocked && !knlislocked), ("kq locked w/o knl locked"));
+
+ KASSERT(!kqislocked || knlislocked, ("kq locked w/o knl locked"));
KNL_ASSERT_LOCK(knl, knlislocked);
mtx_assert(&kn->kn_kq->kq_lock, kqislocked ? MA_OWNED : MA_NOTOWNED);
- if (!kqislocked)
- KASSERT((kn->kn_status & (KN_INFLUX|KN_DETACHED)) == KN_INFLUX,
- ("knlist_remove called w/o knote being KN_INFLUX or already removed"));
+ KASSERT(kqislocked || kn_in_flux(kn), ("knote %p not in flux", kn));
+ KASSERT((kn->kn_status & KN_DETACHED) == 0,
+ ("knote %p was already detached", kn));
if (!knlislocked)
knl->kl_lock(knl->kl_lockarg);
SLIST_REMOVE(&knl->kl_list, kn, knote, kn_selnext);
@@ -2287,30 +2317,30 @@
SLIST_FOREACH_SAFE(kn, &knl->kl_list, kn_selnext, kn2) {
kq = kn->kn_kq;
KQ_LOCK(kq);
- if ((kn->kn_status & KN_INFLUX)) {
+ if (kn_in_flux(kn)) {
KQ_UNLOCK(kq);
continue;
}
knlist_remove_kq(knl, kn, 1, 1);
if (killkn) {
- kn->kn_status |= KN_INFLUX | KN_DETACHED;
+ kn->kn_status |= KN_DETACHED;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
knote_drop(kn, td);
} else {
/* Make sure cleared knotes disappear soon */
- kn->kn_flags |= (EV_EOF | EV_ONESHOT);
+ kn->kn_flags |= EV_EOF | EV_ONESHOT;
KQ_UNLOCK(kq);
}
kq = NULL;
}
if (!SLIST_EMPTY(&knl->kl_list)) {
- /* there are still KN_INFLUX remaining */
+ /* there are still in flux knotes remaining */
kn = SLIST_FIRST(&knl->kl_list);
kq = kn->kn_kq;
KQ_LOCK(kq);
- KASSERT(kn->kn_status & KN_INFLUX,
- ("knote removed w/o list lock"));
+ KASSERT(kn_in_flux(kn), ("knote removed w/o list lock"));
knl->kl_unlock(knl->kl_lockarg);
kq->kq_state |= KQ_FLUXWAIT;
msleep(kq, &kq->kq_lock, PSOCK | PDROP, "kqkclr", 0);
@@ -2352,7 +2382,7 @@
influx = 0;
while (kq->kq_knlistsize > fd &&
(kn = SLIST_FIRST(&kq->kq_knlist[fd])) != NULL) {
- if (kn->kn_status & KN_INFLUX) {
+ if (kn_in_flux(kn)) {
/* someone else might be waiting on our knote */
if (influx)
wakeup(kq);
@@ -2360,7 +2390,7 @@
msleep(kq, &kq->kq_lock, PSOCK, "kqflxwt", 0);
goto again;
}
- kn->kn_status |= KN_INFLUX;
+ kn_enter_flux(kn);
KQ_UNLOCK(kq);
if (!(kn->kn_status & KN_DETACHED))
kn->kn_fop->f_detach(kn);
@@ -2377,7 +2407,7 @@
{
struct klist *list;
- KASSERT(kn->kn_status & KN_INFLUX, ("knote not marked INFLUX"));
+ KASSERT(kn_in_flux(kn), ("knote %p not marked influx", kn));
KQ_OWNED(kq);
if (kn->kn_fop->f_isfd) {
@@ -2395,7 +2425,7 @@
/*
* knote must already have been detached using the f_detach method.
- * no lock need to be held, it is assumed that the KN_INFLUX flag is set
+ * no lock need to be held, it is assumed that the influx state is set
* to prevent other removal.
*/
static void
@@ -2407,10 +2437,10 @@
kq = kn->kn_kq;
KQ_NOTOWNED(kq);
- KASSERT((kn->kn_status & KN_INFLUX) == KN_INFLUX,
- ("knote_drop called without KN_INFLUX set in kn_status"));
-
KQ_LOCK(kq);
+ KASSERT(kn->kn_influx == 1,
+ ("knote_drop called on %p with influx %d", kn, kn->kn_influx));
+
if (kn->kn_fop->f_isfd)
list = &kq->kq_knlist[kn->kn_id];
else
Index: head/sys/sys/event.h
===================================================================
--- head/sys/sys/event.h
+++ head/sys/sys/event.h
@@ -202,8 +202,11 @@
};
/*
- * Setting the KN_INFLUX flag enables you to unlock the kq that this knote
- * is on, and modify kn_status as if you had the KQ lock.
+ * An in-flux knote cannot be dropped from its kq while the kq is
+ * unlocked. If the KN_SCAN flag is not set, a thread can only set
+ * kn_influx when it is exclusive owner of the knote state, and can
+ * modify kn_status as if it had the KQ lock. KN_SCAN must not be set
+ * on a knote which is already in flux.
*
* kn_sfflags, kn_sdata, and kn_kevent are protected by the knlist lock.
*/
@@ -214,16 +217,18 @@
TAILQ_ENTRY(knote) kn_tqe;
struct kqueue *kn_kq; /* which queue we are on */
struct kevent kn_kevent;
+ void *kn_hook;
+ int kn_hookid;
int kn_status; /* protected by kq lock */
#define KN_ACTIVE 0x01 /* event has been triggered */
#define KN_QUEUED 0x02 /* event is on queue */
#define KN_DISABLED 0x04 /* event is disabled */
#define KN_DETACHED 0x08 /* knote is detached */
-#define KN_INFLUX 0x10 /* knote is in flux */
#define KN_MARKER 0x20 /* ignore this knote */
#define KN_KQUEUE 0x40 /* this knote belongs to a kq */
#define KN_HASKQLOCK 0x80 /* for _inevent */
#define KN_SCAN 0x100 /* flux set in kqueue_scan() */
+ int kn_influx;
int kn_sfflags; /* saved filter flags */
intptr_t kn_sdata; /* saved data field */
union {
@@ -234,8 +239,6 @@
void *p_v; /* generic other pointer */
} kn_ptr;
struct filterops *kn_fop;
- void *kn_hook;
- int kn_hookid;
#define kn_id kn_kevent.ident
#define kn_filter kn_kevent.filter
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Mar 16, 4:20 AM (5 h, 58 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29734076
Default Alt Text
D8898.id23284.diff (13 KB)
Attached To
Mode
D8898: Make influx state counted.
Attached
Detach File
Event Timeline
Log In to Comment