summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2015-09-13 11:15:12 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2015-09-13 11:15:12 +0000
commit3d41b8bd3ae0320be70e3e4b939ece3357f1c26a (patch)
tree5f6470d71040237c4b543f9f50e7fe2d678dca8e /sys/kern
parentddde1e0c5aae7abc31f6ba514a8f26c1238eeb96 (diff)
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')
-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
/*