summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2009-11-25 11:01:14 +0000
committerkettenis <kettenis@openbsd.org>2009-11-25 11:01:14 +0000
commitd746c22dec89954371da372e701c622c09423b88 (patch)
tree19c61c25114ba54b2ff7fae0d76edeaf708fcbaf
parentItalian translations (diff)
downloadwireguard-openbsd-d746c22dec89954371da372e701c622c09423b88.tar.xz
wireguard-openbsd-d746c22dec89954371da372e701c622c09423b88.zip
Add a mechanism to stop the scheduler from scheduling processes on a
particular CPU such that it just sits and spins in the idle loop, effectively halting that CPU. ok deraadt@, miod@
-rw-r--r--sys/kern/kern_sched.c14
-rw-r--r--sys/kern/kern_xxx.c21
-rw-r--r--sys/sys/sched.h4
3 files changed, 35 insertions, 4 deletions
diff --git a/sys/kern/kern_sched.c b/sys/kern/kern_sched.c
index 15d57cf037c..6066c6a92f4 100644
--- a/sys/kern/kern_sched.c
+++ b/sys/kern/kern_sched.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sched.c,v 1.14 2009/10/05 17:43:08 deraadt Exp $ */
+/* $OpenBSD: kern_sched.c,v 1.15 2009/11/25 11:01:14 kettenis Exp $ */
/*
* Copyright (c) 2007, 2008 Artur Grabowski <art@openbsd.org>
*
@@ -146,6 +146,11 @@ sched_idle(void *v)
splassert(IPL_NONE);
+ if (spc->spc_schedflags & SPCF_SHOULDHALT) {
+ spc->spc_schedflags |= SPCF_HALTED;
+ wakeup(spc);
+ }
+
cpuset_add(&sched_idle_cpus, ci);
cpu_idle_enter();
while (spc->spc_whichqs == 0)
@@ -246,6 +251,13 @@ sched_chooseproc(void)
SCHED_ASSERT_LOCKED();
+ if (spc->spc_schedflags & SPCF_SHOULDHALT) {
+ p = spc->spc_idleproc;
+ KASSERT(p);
+ p->p_stat = SRUN;
+ return (p);
+ }
+
again:
if (spc->spc_whichqs) {
queue = ffs(spc->spc_whichqs) - 1;
diff --git a/sys/kern/kern_xxx.c b/sys/kern/kern_xxx.c
index 5beade18f06..a842462a218 100644
--- a/sys/kern/kern_xxx.c
+++ b/sys/kern/kern_xxx.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_xxx.c,v 1.12 2009/08/10 11:22:10 deraadt Exp $ */
+/* $OpenBSD: kern_xxx.c,v 1.13 2009/11/25 11:01:14 kettenis Exp $ */
/* $NetBSD: kern_xxx.c,v 1.32 1996/04/22 01:38:41 christos Exp $ */
/*
@@ -53,7 +53,7 @@ sys_reboot(struct proc *p, void *v, register_t *retval)
} */ *uap = v;
CPU_INFO_ITERATOR cii;
struct cpu_info *ci;
- int error;
+ int error, s;
if ((error = suser(p, 0)) != 0)
return (error);
@@ -68,6 +68,23 @@ sys_reboot(struct proc *p, void *v, register_t *retval)
}
}
+ /*
+ * Make sure we stop the secondary CPUs.
+ */
+ s = splstatclock();
+ CPU_INFO_FOREACH(cii, ci) {
+ if (CPU_IS_PRIMARY(ci))
+ continue;
+ ci->ci_schedstate.spc_schedflags |= SPCF_SHOULDHALT;
+ }
+ CPU_INFO_FOREACH(cii, ci) {
+ if (CPU_IS_PRIMARY(ci))
+ continue;
+ while ((ci->ci_schedstate.spc_schedflags & SPCF_HALTED) == 0)
+ tsleep(&ci->ci_schedstate, PZERO, "schedstate", 0);
+ }
+ splx(s);
+
if_downall();
boot(SCARG(uap, opt));
diff --git a/sys/sys/sched.h b/sys/sys/sched.h
index 8211961b815..4220960e480 100644
--- a/sys/sys/sched.h
+++ b/sys/sys/sched.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: sched.h,v 1.22 2009/04/14 09:13:25 art Exp $ */
+/* $OpenBSD: sched.h,v 1.23 2009/11/25 11:01:14 kettenis Exp $ */
/* $NetBSD: sched.h,v 1.2 1999/02/28 18:14:58 ross Exp $ */
/*-
@@ -122,6 +122,8 @@ struct schedstate_percpu {
#define SPCF_SEENRR 0x0001 /* process has seen roundrobin() */
#define SPCF_SHOULDYIELD 0x0002 /* process should yield the CPU */
#define SPCF_SWITCHCLEAR (SPCF_SEENRR|SPCF_SHOULDYIELD)
+#define SPCF_SHOULDHALT 0x0004 /* CPU should be vacated */
+#define SPCF_HALTED 0x0008 /* CPU has been halted */
#define SCHED_PPQ (128 / SCHED_NQS) /* priorities per queue */
#define NICE_WEIGHT 2 /* priorities per nice level */