diff options
author | cheloha <cheloha@cvs.openbsd.org> | 2019-07-03 22:39:34 +0000 |
---|---|---|
committer | cheloha <cheloha@cvs.openbsd.org> | 2019-07-03 22:39:34 +0000 |
commit | 40d389b2bd19834e09052025f12e67335b94fc98 (patch) | |
tree | 3f5428eadae30d9344b2407c5295b0dced7579f5 | |
parent | d5cb3b4efc31fe576d9835223fa53e89d6671346 (diff) |
Add tsleep_nsec(9), msleep_nsec(9), and rwsleep_nsec(9).
Equivalent to their unsuffixed counterparts except that (a) they take
a timeout in terms of nanoseconds, and (b) INFSLP, aka UINT64_MAX (not
zero) indicates that a timeout should not be set.
For now, zero nanoseconds is not a strictly valid invocation: we log a
warning on DIAGNOSTIC kernels if we see such a call. We still sleep
until the next tick in such a case, however. In the future this could
become some sort of poll... TBD.
To facilitate conversions to these interfaces: add inline conversion
functions to sys/time.h for turning your timeout into nanoseconds.
Also do a few easy conversions for warmup and to demonstrate how
further conversions should be done.
Lots of input from mpi@ and ratchov@. Additional input from tedu@,
deraadt@, mortimer@, millert@, and claudio@.
Partly inspired by FreeBSD r247787.
positive feedback from deraadt@, ok mpi@
-rw-r--r-- | share/man/man9/tsleep.9 | 81 | ||||
-rw-r--r-- | sys/kern/kern_acct.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_smr.c | 6 | ||||
-rw-r--r-- | sys/kern/kern_synch.c | 72 | ||||
-rw-r--r-- | sys/sys/systm.h | 9 | ||||
-rw-r--r-- | sys/sys/time.h | 34 | ||||
-rw-r--r-- | sys/uvm/uvm_pdaemon.c | 8 | ||||
-rw-r--r-- | sys/uvm/uvm_pmemrange.c | 5 |
8 files changed, 196 insertions, 25 deletions
diff --git a/share/man/man9/tsleep.9 b/share/man/man9/tsleep.9 index 12edb923003..737a9741776 100644 --- a/share/man/man9/tsleep.9 +++ b/share/man/man9/tsleep.9 @@ -1,4 +1,4 @@ -.\" $OpenBSD: tsleep.9,v 1.12 2018/05/28 18:51:27 cheloha Exp $ +.\" $OpenBSD: tsleep.9,v 1.13 2019/07/03 22:39:33 cheloha Exp $ .\" $NetBSD: sleep.9,v 1.11 1999/03/24 06:15:12 mycroft Exp $ .\" .\" Copyright (c) 1996 The NetBSD Foundation, Inc. @@ -28,13 +28,16 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd $Mdocdate: May 28 2018 $ +.Dd $Mdocdate: July 3 2019 $ .Dt TSLEEP 9 .Os .Sh NAME .Nm tsleep , +.Nm tsleep_nsec , .Nm msleep , +.Nm msleep_nsec , .Nm rwsleep , +.Nm rwsleep_nsec , .Nm wakeup , .Nm wakeup_n , .Nm wakeup_one @@ -42,12 +45,53 @@ .Sh SYNOPSIS .In sys/param.h .In sys/systm.h +.Fd #define INFSLP UINT64_MAX .Ft int -.Fn tsleep "void *ident" "int priority" "const char *wmesg" "int timo" +.Fo tsleep +.Fa "void *ident" +.Fa "int priority" +.Fa "const char *wmesg" +.Fa "int timo" +.Fc .Ft int -.Fn msleep "void *ident" "struct mutex *mtx" "int priority" "const char *wmesg" "int timo" +.Fo tsleep_nsec +.Fa "void *ident" +.Fa "int priority" +.Fa "const char *wmesg" +.Fa "uint64_t nsecs" +.Fc .Ft int -.Fn rwsleep "void *ident" "struct rwlock *rwl" "int priority" "const char *wmesg" "int timo" +.Fo msleep +.Fa "void *ident" +.Fa "struct mutex *mtx" +.Fa "int priority" +.Fa "const char *wmesg" +.Fa "int timo" +.Fc +.Ft int +.Fo msleep_nsec +.Fa "void *ident" +.Fa "struct mutex *mtx" +.Fa "int priority" +.Fa "const char *wmesg" +.Fa "uint64_t nsecs" +.Fc +.Ft int +.Fo rwsleep +.Fa "void *ident" +.Fa "struct rwlock *rwl" +.Fa "int priority" +.Fa "const char *wmesg" +.Fa "int timo" +.Fc +.Ft int +.Fo rwsleep_nsec +.Fa "void *ident" +.Fa "struct rwlock *rwl" +.Fa "int priority" +.Fa "const char *wmesg" +.Fa "uint64_t nsecs" +.Fc .Ft void .Fn wakeup "void *ident" .Ft void @@ -166,6 +210,26 @@ argument. .El .Pp The +.Fn tsleep_nsec , +.Fn msleep_nsec , +and +.Fn rwsleep_nsec +functions behave like their unsuffixed counterparts except that they +accept a timeout in terms of nanoseconds. +These functions will always sleep for at least one tick, +even if +.Fa nsecs +is zero. +If +.Fa nsecs +is equal to +.Dv INFSLP +these functions do not time out, +otherwise they sleep for at most +.Fa nsecs +nanoseconds. +.Pp +The .Fn wakeup function will mark all processes which are currently sleeping on the identifier .Fa ident @@ -194,9 +258,12 @@ except that only or one process, respectively, is marked runnable. .Sh RETURN VALUES .Fn tsleep , -.Fn msleep +.Fn tsleep_nsec , +.Fn msleep , +.Fn msleep_nsec , +.Fn rwsleep , and -.Fn rwsleep +.Fn rwsleep_nsec 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_acct.c b/sys/kern/kern_acct.c index 3bf3ae26c9a..db8494f292d 100644 --- a/sys/kern/kern_acct.c +++ b/sys/kern/kern_acct.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_acct.c,v 1.38 2019/06/01 14:11:17 mpi Exp $ */ +/* $OpenBSD: kern_acct.c,v 1.39 2019/07/03 22:39:33 cheloha Exp $ */ /* $NetBSD: kern_acct.c,v 1.42 1996/02/04 02:15:12 christos Exp $ */ /*- @@ -86,7 +86,7 @@ struct vnode *savacctp; */ int acctsuspend = 2; /* stop accounting when < 2% free space left */ int acctresume = 4; /* resume when free space risen to > 4% */ -int acctchkfreq = 15; /* frequency (in seconds) to check space */ +int acctrate = 15; /* delay (in seconds) between space checks */ struct proc *acct_proc; @@ -313,7 +313,7 @@ acct_thread(void *arg) } else { break; } - tsleep(&acct_proc, PPAUSE, "acct", acctchkfreq *hz); + tsleep_nsec(&acct_proc, PPAUSE, "acct", SEC_TO_NSEC(acctrate)); } acct_proc = NULL; kthread_exit(0); diff --git a/sys/kern/kern_smr.c b/sys/kern/kern_smr.c index 96cf9ca5cdc..ffe7b9b5527 100644 --- a/sys/kern/kern_smr.c +++ b/sys/kern/kern_smr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_smr.c,v 1.4 2019/05/17 03:53:08 visa Exp $ */ +/* $OpenBSD: kern_smr.c,v 1.5 2019/07/03 22:39:33 cheloha Exp $ */ /* * Copyright (c) 2019 Visa Hankala @@ -100,8 +100,8 @@ smr_thread(void *arg) "bored", 0); } else { if (smr_expedite == 0) - msleep(&smr_ndeferred, &smr_lock, PVM, - "pause", SMR_PAUSE * hz / 1000); + msleep_nsec(&smr_ndeferred, &smr_lock, PVM, + "pause", MSEC_TO_NSEC(SMR_PAUSE)); } SIMPLEQ_CONCAT(&deferred, &smr_deferred); diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index 378c25cadaf..98e85a5bd68 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_synch.c,v 1.149 2019/06/18 15:53:11 visa Exp $ */ +/* $OpenBSD: kern_synch.c,v 1.150 2019/07/03 22:39:33 cheloha Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /* @@ -55,6 +55,10 @@ #include <machine/spinlock.h> +#ifdef DIAGNOSTIC +#include <sys/syslog.h> +#endif + #ifdef KTRACE #include <sys/ktrace.h> #endif @@ -149,6 +153,28 @@ tsleep(const volatile void *ident, int priority, const char *wmesg, int timo) } int +tsleep_nsec(const volatile void *ident, int priority, const char *wmesg, + uint64_t nsecs) +{ + uint64_t to_ticks; + + if (nsecs == INFSLP) + return tsleep(ident, priority, wmesg, 0); +#ifdef DIAGNOSTIC + if (nsecs == 0) { + log(LOG_WARNING, "%s: %s: trying to sleep for zero nanoseconds", + __func__, wmesg); + } +#endif + to_ticks = nsecs / (tick * 1000); + if (to_ticks > INT_MAX) + to_ticks = INT_MAX; + if (to_ticks == 0) + to_ticks = 1; + return tsleep(ident, priority, wmesg, (int)to_ticks); +} + +int sleep_finish_all(struct sleep_state *sls, int do_sleep) { int error, error1; @@ -228,6 +254,28 @@ msleep(const volatile void *ident, struct mutex *mtx, int priority, return error; } +int +msleep_nsec(const volatile void *ident, struct mutex *mtx, int priority, + const char *wmesg, uint64_t nsecs) +{ + uint64_t to_ticks; + + if (nsecs == INFSLP) + return msleep(ident, mtx, priority, wmesg, 0); +#ifdef DIAGNOSTIC + if (nsecs == 0) { + log(LOG_WARNING, "%s: %s: trying to sleep for zero nanoseconds", + __func__, wmesg); + } +#endif + to_ticks = nsecs / (tick * 1000); + if (to_ticks > INT_MAX) + to_ticks = INT_MAX; + if (to_ticks == 0) + to_ticks = 1; + return msleep(ident, mtx, priority, wmesg, (int)to_ticks); +} + /* * 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. @@ -257,6 +305,28 @@ rwsleep(const volatile void *ident, struct rwlock *rwl, int priority, return error; } +int +rwsleep_nsec(const volatile void *ident, struct rwlock *rwl, int priority, + const char *wmesg, uint64_t nsecs) +{ + uint64_t to_ticks; + + if (nsecs == INFSLP) + return rwsleep(ident, rwl, priority, wmesg, 0); +#ifdef DIAGNOSTIC + if (nsecs == 0) { + log(LOG_WARNING, "%s: %s: trying to sleep for zero nanoseconds", + __func__, wmesg); + } +#endif + to_ticks = nsecs / (tick * 1000); + if (to_ticks > INT_MAX) + to_ticks = INT_MAX; + if (to_ticks == 0) + to_ticks = 1; + return rwsleep(ident, rwl, priority, wmesg, (int)to_ticks); +} + 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 e84008592f1..78fa758b015 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: systm.h,v 1.141 2019/04/23 13:35:12 visa Exp $ */ +/* $OpenBSD: systm.h,v 1.142 2019/07/03 22:39:33 cheloha Exp $ */ /* $NetBSD: systm.h,v 1.50 1996/06/09 04:55:09 briggs Exp $ */ /*- @@ -259,14 +259,21 @@ void cond_init(struct cond *); void cond_wait(struct cond *, const char *); void cond_signal(struct cond *); +#define INFSLP UINT64_MAX + 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 tsleep_nsec(const volatile void *, int, const char *, uint64_t); int msleep(const volatile void *, struct mutex *, int, const char*, int); +int msleep_nsec(const volatile void *, struct mutex *, int, const char*, + uint64_t); int rwsleep(const volatile void *, struct rwlock *, int, const char *, int); +int rwsleep_nsec(const volatile void *, struct rwlock *, int, const char *, + uint64_t); void yield(void); void wdog_register(int (*)(void *, int), void *); diff --git a/sys/sys/time.h b/sys/sys/time.h index 83f7ad510bf..924ece4f1f8 100644 --- a/sys/sys/time.h +++ b/sys/sys/time.h @@ -1,4 +1,4 @@ -/* $OpenBSD: time.h,v 1.43 2019/07/02 14:54:36 cheloha Exp $ */ +/* $OpenBSD: time.h,v 1.44 2019/07/03 22:39:33 cheloha Exp $ */ /* $NetBSD: time.h,v 1.18 1996/04/23 10:29:33 mycroft Exp $ */ /* @@ -340,10 +340,36 @@ NSEC_TO_TIMEVAL(uint64_t ns, struct timeval *tv) } static __inline void -NSEC_TO_TIMESPEC(uint64_t ns, struct timespec *tv) +NSEC_TO_TIMESPEC(uint64_t ns, struct timespec *ts) { - tv->tv_sec = ns / 1000000000L; - tv->tv_nsec = ns % 1000000000L; + ts->tv_sec = ns / 1000000000L; + ts->tv_nsec = ns % 1000000000L; +} + +#include <sys/stdint.h> + +static __inline uint64_t +SEC_TO_NSEC(uint64_t seconds) +{ + if (seconds > UINT64_MAX / 1000000000ULL) + return UINT64_MAX; + return seconds * 1000000000ULL; +} + +static __inline uint64_t +MSEC_TO_NSEC(uint64_t milliseconds) +{ + if (milliseconds > UINT64_MAX / 1000000ULL) + return UINT64_MAX; + return milliseconds * 1000000ULL; +} + +static __inline uint64_t +USEC_TO_NSEC(uint64_t microseconds) +{ + if (microseconds > UINT64_MAX / 1000ULL) + return UINT64_MAX; + return microseconds * 1000ULL; } #else /* !_KERNEL */ diff --git a/sys/uvm/uvm_pdaemon.c b/sys/uvm/uvm_pdaemon.c index e310bd5b200..5228338d7f5 100644 --- a/sys/uvm/uvm_pdaemon.c +++ b/sys/uvm/uvm_pdaemon.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_pdaemon.c,v 1.82 2019/05/10 02:33:57 beck Exp $ */ +/* $OpenBSD: uvm_pdaemon.c,v 1.83 2019/07/03 22:39:33 cheloha Exp $ */ /* $NetBSD: uvm_pdaemon.c,v 1.23 2000/08/20 10:24:14 bjh21 Exp $ */ /* @@ -110,7 +110,7 @@ void uvmpd_drop(struct pglist *); void uvm_wait(const char *wmsg) { - int timo = 0; + uint64_t timo = INFSLP; #ifdef DIAGNOSTIC if (curproc == &proc0) @@ -140,7 +140,7 @@ uvm_wait(const char *wmsg) */ printf("pagedaemon: deadlock detected!\n"); - timo = hz >> 3; /* set timeout */ + timo = MSEC_TO_NSEC(125); /* set timeout */ #if defined(DEBUG) /* DEBUG: panic so we can debug it */ panic("pagedaemon deadlock"); @@ -149,7 +149,7 @@ uvm_wait(const char *wmsg) uvm_lock_fpageq(); wakeup(&uvm.pagedaemon); /* wake the daemon! */ - msleep(&uvmexp.free, &uvm.fpageqlock, PVM | PNORELOCK, wmsg, timo); + msleep_nsec(&uvmexp.free, &uvm.fpageqlock, PVM | PNORELOCK, wmsg, timo); } /* diff --git a/sys/uvm/uvm_pmemrange.c b/sys/uvm/uvm_pmemrange.c index cd92c319650..7d9e2a52b67 100644 --- a/sys/uvm/uvm_pmemrange.c +++ b/sys/uvm/uvm_pmemrange.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_pmemrange.c,v 1.54 2019/05/09 20:36:44 beck Exp $ */ +/* $OpenBSD: uvm_pmemrange.c,v 1.55 2019/07/03 22:39:33 cheloha Exp $ */ /* * Copyright (c) 2009, 2010 Ariane van der Steldt <ariane@stack.nl> @@ -1928,7 +1928,8 @@ uvm_wait_pla(paddr_t low, paddr_t high, paddr_t size, int failok) * uvm_wait(), as this is exactly the same issue. */ printf("pagedaemon: wait_pla deadlock detected!\n"); - msleep(&uvmexp.free, &uvm.fpageqlock, PVM, wmsg, hz >> 3); + msleep_nsec(&uvmexp.free, &uvm.fpageqlock, PVM, wmsg, + MSEC_TO_NSEC(125)); #if defined(DEBUG) /* DEBUG: panic so we can debug it */ panic("wait_pla pagedaemon deadlock"); |