summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorcheloha <cheloha@openbsd.org>2021-01-14 03:32:01 +0000
committercheloha <cheloha@openbsd.org>2021-01-14 03:32:01 +0000
commit59ca1c103e160f9e603455f30bde94d63bb7e3cf (patch)
treed98b35866590f7a894e1a116f893a3a7fd24c56b /sys/kern
parentMake vm_rpc_send_rpci_tx_buf() use the buffer passed in, not the buffer (diff)
downloadwireguard-openbsd-59ca1c103e160f9e603455f30bde94d63bb7e3cf.tar.xz
wireguard-openbsd-59ca1c103e160f9e603455f30bde94d63bb7e3cf.zip
syncer_thread: sleep without lbolt
The syncer_thread() uses lbolt to perform periodic execution. We can do this without lbolt. - Adding a local wakeup(9) channel (syncer_chan) and sleep on it. - Use a local copy of getnsecuptime() to get 1/hz resolution for time measurements. This is much better than using gettime(9), which is wholly unsuitable for this use case. Measure how long we spend in the loop and use this to calculate how long to sleep until the next execution. NB: getnsecuptime() is probably ready to be moved to kern_tc.c and documented. - Using the system uptime instead of the UTC time avoids issues with time jumps. ok mpi@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_sync.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/sys/kern/vfs_sync.c b/sys/kern/vfs_sync.c
index 62693a1d2f0..b7d16fa3b6b 100644
--- a/sys/kern/vfs_sync.c
+++ b/sys/kern/vfs_sync.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_sync.c,v 1.64 2020/06/24 22:03:41 cheloha Exp $ */
+/* $OpenBSD: vfs_sync.c,v 1.65 2021/01/14 03:32:01 cheloha Exp $ */
/*
* Portions of this code are:
@@ -48,6 +48,7 @@
#include <sys/vnode.h>
#include <sys/lock.h>
#include <sys/malloc.h>
+#include <sys/time.h>
#include <sys/kernel.h>
#include <sys/sched.h>
@@ -73,6 +74,7 @@ LIST_HEAD(synclist, vnode);
static struct synclist *syncer_workitem_pending;
struct proc *syncerproc;
+int syncer_chan;
/*
* The workitem queue.
@@ -130,19 +132,32 @@ vn_syncer_add_to_worklist(struct vnode *vp, int delay)
}
/*
+ * TODO Move getnsecuptime() to kern_tc.c and document it when we have
+ * more users in the kernel.
+ */
+static uint64_t
+getnsecuptime(void)
+{
+ struct timespec now;
+
+ getnanouptime(&now);
+ return TIMESPEC_TO_NSEC(&now);
+}
+
+/*
* System filesystem synchronizer daemon.
*/
void
syncer_thread(void *arg)
{
+ uint64_t elapsed, start;
struct proc *p = curproc;
struct synclist *slp;
struct vnode *vp;
- time_t starttime;
int s;
for (;;) {
- starttime = gettime();
+ start = getnsecuptime();
/*
* Push files whose dirty time has expired.
@@ -220,6 +235,7 @@ syncer_thread(void *arg)
rushjob -= 1;
continue;
}
+
/*
* If it has taken us less than a second to process the
* current work, then wait. Otherwise start right over
@@ -228,8 +244,11 @@ syncer_thread(void *arg)
* matter as we are just trying to generally pace the
* filesystem activity.
*/
- if (gettime() == starttime)
- tsleep_nsec(&lbolt, PPAUSE, "syncer", INFSLP);
+ elapsed = getnsecuptime() - start;
+ if (elapsed < SEC_TO_NSEC(1)) {
+ tsleep_nsec(&syncer_chan, PPAUSE, "syncer",
+ SEC_TO_NSEC(1) - elapsed);
+ }
}
}
@@ -242,7 +261,7 @@ int
speedup_syncer(void)
{
if (syncerproc)
- wakeup_proc(syncerproc, &lbolt);
+ wakeup_proc(syncerproc, &syncer_chan);
if (rushjob < syncdelay / 2) {
rushjob += 1;
stat_rush_requests += 1;