summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcheloha <cheloha@cvs.openbsd.org>2019-07-03 22:39:34 +0000
committercheloha <cheloha@cvs.openbsd.org>2019-07-03 22:39:34 +0000
commit40d389b2bd19834e09052025f12e67335b94fc98 (patch)
tree3f5428eadae30d9344b2407c5295b0dced7579f5
parentd5cb3b4efc31fe576d9835223fa53e89d6671346 (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.981
-rw-r--r--sys/kern/kern_acct.c6
-rw-r--r--sys/kern/kern_smr.c6
-rw-r--r--sys/kern/kern_synch.c72
-rw-r--r--sys/sys/systm.h9
-rw-r--r--sys/sys/time.h34
-rw-r--r--sys/uvm/uvm_pdaemon.c8
-rw-r--r--sys/uvm/uvm_pmemrange.c5
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");