summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_shutdown.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_shutdown.c')
-rw-r--r--sys/kern/kern_shutdown.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/sys/kern/kern_shutdown.c b/sys/kern/kern_shutdown.c
index 1afa80f..90b3642 100644
--- a/sys/kern/kern_shutdown.c
+++ b/sys/kern/kern_shutdown.c
@@ -131,21 +131,23 @@ shutdown_conf(void *unused)
SYSINIT(shutdown_conf, SI_SUB_INTRINSIC, SI_ORDER_ANY, shutdown_conf, NULL)
-/* ARGSUSED */
-
/*
* The system call that results in a reboot
+ *
+ * MPSAFE
*/
+/* ARGSUSED */
int
reboot(struct proc *p, struct reboot_args *uap)
{
int error;
- if ((error = suser(p)))
- return (error);
-
- boot(uap->opt);
- return (0);
+ mtx_lock(&Giant);
+ if ((error = suser(p)) == 0) {
+ boot(uap->opt);
+ }
+ mtx_unlock(&Giant);
+ return (error);
}
/*
@@ -565,14 +567,27 @@ static u_int panic_cpu = NOCPU;
* Panic is called on unresolvable fatal errors. It prints "panic: mesg",
* and then reboots. If we are called twice, then we avoid trying to sync
* the disks as this often leads to recursive panics.
+ *
+ * MPSAFE
*/
void
panic(const char *fmt, ...)
{
int bootopt;
+ int holding_giant = 0;
va_list ap;
static char buf[256];
+#if 0
+ /*
+ * We must hold Giant when entering a panic
+ */
+ if (!mtx_owned(&Giant)) {
+ mtx_lock(&Giant);
+ holding_giant = 1;
+ }
+#endif
+
#ifdef SMP
/*
* We don't want multiple CPU's to panic at the same time, so we
@@ -580,11 +595,13 @@ panic(const char *fmt, ...)
* panic_cpu if we are spinning in case the panic on the first
* CPU is canceled.
*/
- if (panic_cpu != PCPU_GET(cpuid))
+ if (panic_cpu != PCPU_GET(cpuid)) {
while (atomic_cmpset_int(&panic_cpu, NOCPU,
- PCPU_GET(cpuid)) == 0)
+ PCPU_GET(cpuid)) == 0) {
while (panic_cpu != NOCPU)
; /* nothing */
+ }
+ }
#endif
bootopt = RB_AUTOBOOT | RB_DUMP;
@@ -616,6 +633,8 @@ panic(const char *fmt, ...)
#ifdef SMP
atomic_store_rel_int(&panic_cpu, NOCPU);
#endif
+ if (holding_giant)
+ mtx_unlock(&Giant);
return;
}
#endif
OpenPOWER on IntegriCloud