diff --git a/share/man/man9/Makefile b/share/man/man9/Makefile index 8acef3581782..e5778a1f8fff 100644 --- a/share/man/man9/Makefile +++ b/share/man/man9/Makefile @@ -773,6 +773,8 @@ MLINKS+=kqueue.9 knlist_add.9 \ kqueue.9 knlist_destroy.9 \ kqueue.9 knlist_empty.9 \ kqueue.9 knlist_init.9 \ + kqueue.9 knlist_init_mtx.9 \ + kqueue.9 knlist_init_rw_reader.9 \ kqueue.9 knlist_remove.9 \ kqueue.9 knlist_remove_inevent.9 \ kqueue.9 knote_fdclose.9 \ diff --git a/share/man/man9/kqueue.9 b/share/man/man9/kqueue.9 index 2ecc08be5ddf..555fe545e611 100644 --- a/share/man/man9/kqueue.9 +++ b/share/man/man9/kqueue.9 @@ -24,14 +24,14 @@ .\" .\" $FreeBSD$ .\" -.Dd February 25, 2012 +.Dd March 26, 2012 .Dt KQUEUE 9 .Os .Sh NAME .Nm kqueue_add_filteropts , kqueue_del_filteropts , .Nm kqfd_register , .Nm knote_fdclose , -.Nm knlist_init , knlist_init_mtx , +.Nm knlist_init , knlist_init_mtx , knlist_init_rw_reader , .Nm knlist_add , knlist_remove , knlist_remove_inevent , knlist_empty , .Nm knlist_clear , knlist_delete , knlist_destroy , .Nm KNOTE_LOCKED , KNOTE_UNLOCKED @@ -57,6 +57,8 @@ .Ft void .Fn knlist_init_mtx "struct knlist *knl" "struct mtx *lock" .Ft void +.Fn knlist_init_rw_reader "struct knlist *knl" "struct rwlock *lock" +.Ft void .Fn knlist_add "struct knlist *knl" "struct knote *kn" "int islocked" .Ft void .Fn knlist_remove "struct knlist *knl" "struct knote *kn" "int islocked" @@ -259,8 +261,10 @@ If used, the .Vt knlist must be initialized with either .Fn knlist_init +, +.Fn knlist_init_mtx or -.Fn knlist_init_mtx . +.Fn knlist_init_rw_reader . The .Vt knlist structure may be embedded into the object structure. @@ -305,6 +309,19 @@ style lock. .Pp The function +.Fn knlist_init_rw_reader +may be used to initialize a +.Vt knlist +when +.Fa lock +is a +.Xr rwlock 9 +read lock. +Lock is acquired via +.Fn rw_rlock +function. +.Pp +The function .Fn knlist_empty returns true when there are no .Vt knotes diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 925cbecd0b49..443d902b1047 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -1869,6 +1870,7 @@ knlist_remove_inevent(struct knlist *knl, struct knote *kn) int knlist_empty(struct knlist *knl) { + KNL_ASSERT_LOCKED(knl); return SLIST_EMPTY(&knl->kl_list); } @@ -1882,27 +1884,59 @@ static void knlist_mtx_unlock(void *arg); static void knlist_mtx_lock(void *arg) { + mtx_lock((struct mtx *)arg); } static void knlist_mtx_unlock(void *arg) { + mtx_unlock((struct mtx *)arg); } static void knlist_mtx_assert_locked(void *arg) { + mtx_assert((struct mtx *)arg, MA_OWNED); } static void knlist_mtx_assert_unlocked(void *arg) { + mtx_assert((struct mtx *)arg, MA_NOTOWNED); } +static void +knlist_rw_rlock(void *arg) +{ + + rw_rlock((struct rwlock *)arg); +} + +static void +knlist_rw_runlock(void *arg) +{ + + rw_runlock((struct rwlock *)arg); +} + +static void +knlist_rw_assert_locked(void *arg) +{ + + rw_assert((struct rwlock *)arg, RA_LOCKED); +} + +static void +knlist_rw_assert_unlocked(void *arg) +{ + + rw_assert((struct rwlock *)arg, RA_UNLOCKED); +} + void knlist_init(struct knlist *knl, void *lock, void (*kl_lock)(void *), void (*kl_unlock)(void *), @@ -1941,6 +1975,14 @@ knlist_init_mtx(struct knlist *knl, struct mtx *lock) knlist_init(knl, lock, NULL, NULL, NULL, NULL); } +void +knlist_init_rw_reader(struct knlist *knl, struct rwlock *lock) +{ + + knlist_init(knl, lock, knlist_rw_rlock, knlist_rw_runlock, + knlist_rw_assert_locked, knlist_rw_assert_unlocked); +} + void knlist_destroy(struct knlist *knl) { diff --git a/sys/sys/event.h b/sys/sys/event.h index 08072a776edd..707fbed7001d 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -234,6 +234,7 @@ struct thread; struct proc; struct knlist; struct mtx; +struct rwlock; extern void knote(struct knlist *list, long hint, int lockflags); extern void knote_fork(struct knlist *list, int pid); @@ -245,6 +246,7 @@ extern void knlist_init(struct knlist *knl, void *lock, void (*kl_lock)(void *), void (*kl_unlock)(void *), void (*kl_assert_locked)(void *), void (*kl_assert_unlocked)(void *)); extern void knlist_init_mtx(struct knlist *knl, struct mtx *lock); +extern void knlist_init_rw_reader(struct knlist *knl, struct rwlock *lock); extern void knlist_destroy(struct knlist *knl); extern void knlist_cleardel(struct knlist *knl, struct thread *td, int islocked, int killkn);