summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sched.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2015-09-13 11:15:11 +0000
committerkettenis <kettenis@openbsd.org>2015-09-13 11:15:11 +0000
commitf30f8d91251ec32bb5d76e126ed64a692262a742 (patch)
treef4155fc8362d03a33929944be2ffd261c93c8b79 /sys/kern/kern_sched.c
parentAdd Certplus CA root certificate: (diff)
downloadwireguard-openbsd-f30f8d91251ec32bb5d76e126ed64a692262a742.tar.xz
wireguard-openbsd-f30f8d91251ec32bb5d76e126ed64a692262a742.zip
Introduce sched_barrier(9), an interface that acts as a scheduler barrier in
the sense that it guarantees that the specified CPU went through the scheduler. This also guarantees that interrupt handlers running on that CPU will have finished when sched_barrier() returns. ok miod@, guenther@
Diffstat (limited to 'sys/kern/kern_sched.c')
-rw-r--r--sys/kern/kern_sched.c47
1 files changed, 46 insertions, 1 deletions
diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c
index 1382840d3f8..089e9bf7e67 100644
--- a/sys/kern/kern_sched.c
+++ b/sys/kern/kern_sched.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sched.c,v 1.36 2015/03/14 03:38:50 jsg Exp $ */
+/* $OpenBSD: kern_sched.c,v 1.37 2015/09/13 11:15:11 kettenis Exp $ */
/*
* Copyright (c) 2007, 2008 Artur Grabowski <art@openbsd.org>
*
@@ -24,6 +24,7 @@
#include <sys/resourcevar.h>
#include <sys/signalvar.h>
#include <sys/mutex.h>
+#include <sys/task.h>
#include <uvm/uvm_extern.h>
@@ -634,6 +635,50 @@ sched_stop_secondary_cpus(void)
}
}
+void
+sched_barrier_task(void *arg)
+{
+ struct cpu_info *ci = arg;
+
+ sched_peg_curproc(ci);
+ ci->ci_schedstate.spc_barrier = 1;
+ wakeup(&ci->ci_schedstate.spc_barrier);
+ atomic_clearbits_int(&curproc->p_flag, P_CPUPEG);
+}
+
+void
+sched_barrier(struct cpu_info *ci)
+{
+ struct sleep_state sls;
+ struct task task;
+ CPU_INFO_ITERATOR cii;
+ struct schedstate_percpu *spc;
+
+ if (ci == NULL) {
+ CPU_INFO_FOREACH(cii, ci) {
+ if (CPU_IS_PRIMARY(ci))
+ break;
+ }
+ }
+ KASSERT(ci != NULL);
+ spc = &ci->ci_schedstate;
+
+ task_set(&task, sched_barrier_task, ci);
+ spc->spc_barrier = 0;
+ task_add(systq, &task);
+ while (!spc->spc_barrier) {
+ sleep_setup(&sls, &spc->spc_barrier, PWAIT, "sbar");
+ sleep_finish(&sls, !spc->spc_barrier);
+ }
+}
+
+#else
+
+void
+sched_barrier(struct cpu_info *ci)
+{
+}
+
#endif
/*