diff options
author | kib <kib@FreeBSD.org> | 2015-09-16 04:35:23 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2015-09-16 04:35:23 +0000 |
commit | 6b2dbe45194d69ff67dc5072e7ba1f4685adcafe (patch) | |
tree | 1489d46fec3a709768062aeee70d24a4add3cc39 | |
parent | 1e1e7173daef39513d3c7a059b7c998267578564 (diff) | |
download | FreeBSD-src-6b2dbe45194d69ff67dc5072e7ba1f4685adcafe.zip FreeBSD-src-6b2dbe45194d69ff67dc5072e7ba1f4685adcafe.tar.gz |
MFC r287366:
Use SLIST_FOREACH_SAFE() to fix iteration.
-rw-r--r-- | sys/kern/kern_event.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 9de8fa7..dae1d54 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1849,7 +1849,7 @@ void knote(struct knlist *list, long hint, int lockflags) { struct kqueue *kq; - struct knote *kn; + struct knote *kn, *tkn; int error; if (list == NULL) @@ -1861,14 +1861,13 @@ knote(struct knlist *list, long hint, int lockflags) list->kl_lock(list->kl_lockarg); /* - * If we unlock the list lock (and set KN_INFLUX), we can eliminate - * the kqueue scheduling, but this will introduce four - * lock/unlock's for each knote to test. If we do, continue to use - * SLIST_FOREACH, SLIST_FOREACH_SAFE is not safe in our case, it is - * only safe if you want to remove the current item, which we are - * not doing. + * If we unlock the list lock (and set KN_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 + * or other threads could remove events. */ - SLIST_FOREACH(kn, &list->kl_list, kn_selnext) { + 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) { |