diff options
author | 2016-09-13 08:32:44 +0000 | |
---|---|---|
committer | 2016-09-13 08:32:44 +0000 | |
commit | c4a692e11cc0acf8537c55240cc1a62ec965211e (patch) | |
tree | 3a1b8be8f4581a80626d3dd98169b351eb940038 | |
parent | Split if_linkstate_task() in two to avoid SPL recursion when the (diff) | |
download | wireguard-openbsd-c4a692e11cc0acf8537c55240cc1a62ec965211e.tar.xz wireguard-openbsd-c4a692e11cc0acf8537c55240cc1a62ec965211e.zip |
Introduce rwsleep(9), an equivalent to msleep(9) but for code protected
by a write lock.
ok guenther@, vgross@
-rw-r--r-- | share/man/man9/tsleep.9 | 33 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 36 | ||||
-rw-r--r-- | sys/sys/systm.h | 4 |
3 files changed, 65 insertions, 8 deletions
diff --git a/share/man/man9/tsleep.9 b/share/man/man9/tsleep.9 index 391421e86a2..be5cf84d18d 100644 --- a/share/man/man9/tsleep.9 +++ b/share/man/man9/tsleep.9 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tsleep.9,v 1.10 2015/09/14 15:14:55 schwarze Exp $ +.\" $OpenBSD: tsleep.9,v 1.11 2016/09/13 08:32:44 mpi Exp $ .\" $NetBSD: sleep.9,v 1.11 1999/03/24 06:15:12 mycroft Exp $ .\" .\" Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -28,12 +28,13 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: September 14 2015 $ +.Dd $Mdocdate: September 13 2016 $ .Dt TSLEEP 9 .Os .Sh NAME .Nm tsleep , .Nm msleep , +.Nm rwsleep , .Nm wakeup , .Nm wakeup_n , .Nm wakeup_one @@ -45,6 +46,8 @@ .Fn tsleep "void *ident" "int priority" "const char *wmesg" "int timo" .Ft int .Fn msleep "void *ident" "struct mutex *mtx" "int priority" "const char *wmesg" "int timo" +.Ft int +.Fn rwsleep "void *ident" "struct rwlock *wl" "int priority" "const char *wmesg" "int timo" .Ft void .Fn wakeup "void *ident" .Ft void @@ -53,9 +56,10 @@ .Fn wakeup_one "void *ident" .Sh DESCRIPTION These functions implement voluntary context switching. -.Fn tsleep -and +.Fn tsleep , .Fn msleep +and +.Fn rwsleep are used throughout the kernel whenever processing in the current context cannot continue for any of the following reasons: .Bl -bullet -offset indent @@ -146,6 +150,22 @@ argument. .El .Pp The +.Fn rwsleep +function behaves just like +.Fn tsleep , +but takes an additional argument: +.Bl -tag -width priority +.It Fa wl +A write lock that will be unlocked when the process is safely +on the sleep queue. +The write lock will be relocked at the end of rwsleep unless the +.Dv PNORELOCK +flag is set in the +.Fa priority +argument. +.El +.Pp +The .Fn wakeup function will mark all processes which are currently sleeping on the identifier .Fa ident @@ -173,9 +193,10 @@ except that only .Fa count or one process, respectively, is marked runnable. .Sh RETURN VALUES -.Fn tsleep -and +.Fn tsleep , .Fn msleep +and +.Fn rwsleep return 0 if they return as a result of a .Fn wakeup . If they return as a result of a signal, the return value is diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 4e87d06b64b..beeefe06458 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_synch.c,v 1.134 2016/09/03 15:06:06 akfaew Exp $ */ +/* $OpenBSD: kern_synch.c,v 1.135 2016/09/13 08:32:44 mpi Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /* @@ -226,6 +226,40 @@ msleep(const volatile void *ident, struct mutex *mtx, int priority, return (error); } +/* + * Same as tsleep, but if we have a rwlock provided, then once we've + * entered the sleep queue we drop the it. After sleeping we re-lock. + */ +int +rwsleep(const volatile void *ident, struct rwlock *wl, int priority, + const char *wmesg, int timo) +{ + struct sleep_state sls; + int error, error1; + + KASSERT((priority & ~(PRIMASK | PCATCH | PNORELOCK)) == 0); + rw_assert_wrlock(wl); + + sleep_setup(&sls, ident, priority, wmesg); + sleep_setup_timeout(&sls, timo); + sleep_setup_signal(&sls, priority); + + rw_exit_write(wl); + + sleep_finish(&sls, 1); + error1 = sleep_finish_timeout(&sls); + error = sleep_finish_signal(&sls); + + if ((priority & PNORELOCK) == 0) + rw_enter_write(wl); + + /* Signal errors are higher priority than timeouts. */ + if (error == 0 && error1 != 0) + error = error1; + + return (error); +} + void sleep_setup(struct sleep_state *sls, const volatile void *ident, int prio, const char *wmesg) diff --git a/sys/sys/systm.h b/sys/sys/systm.h index 374805b91b8..36a2e83fd22 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systm.h,v 1.116 2016/09/04 09:22:29 mpi Exp $ */ +/* $OpenBSD: systm.h,v 1.117 2016/09/13 08:32:44 mpi Exp $ */ /* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */ /*- @@ -246,11 +246,13 @@ int sleep_finish_signal(struct sleep_state *); void sleep_queue_init(void); struct mutex; +struct rwlock; void wakeup_n(const volatile void *, int); void wakeup(const volatile void *); #define wakeup_one(c) wakeup_n((c), 1) int tsleep(const volatile void *, int, const char *, int); int msleep(const volatile void *, struct mutex *, int, const char*, int); +int rwsleep(const volatile void *, struct rwlock *, int, const char *, int); void yield(void); void wdog_register(int (*)(void *, int), void *); |