diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-09-13 11:15:12 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2015-09-13 11:15:12 +0000 |
commit | 3d41b8bd3ae0320be70e3e4b939ece3357f1c26a (patch) | |
tree | 5f6470d71040237c4b543f9f50e7fe2d678dca8e /sys/kern | |
parent | ddde1e0c5aae7abc31f6ba514a8f26c1238eeb96 (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.c | 47 |
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 /* |