DragonFlyBSD Kernel Audit
DF-0239 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/kern_kthread.c b/sys/kern/kern_kthread.c
--- a/sys/kern/kern_kthread.c
+++ b/sys/kern/kern_kthread.c
@@ -205,6 +205,34 @@
 	}
 }
 
+/*
+ * DF-0239: resume a kernel process previously suspended with
+ * suspend_kproc().  This was declared in <sys/kthread.h> but never
+ * implemented, so a suspended daemon (syncer, bufdaemon, swapcache,
+ * mountd, printf, hptmv, ...) would spin forever in
+ * kproc_suspend_loop() waiting for TDF_MP_WAKEREQ and never wake up.
+ */
+int
+resume_kproc(struct thread *td)
+{
+	if (td->td_proc == NULL) {
+		lwkt_gettoken(&kpsus_token);
+		/* request thread resume */
+		atomic_set_int(&td->td_mpflags, TDF_MP_WAKEREQ);
+		wakeup(td);
+		while (td->td_mpflags & TDF_MP_WAKEREQ) {
+			int error = tsleep(td, 0, "reskp", 0);
+			if (error == EWOULDBLOCK)
+				break;
+		}
+		atomic_clear_int(&td->td_mpflags, TDF_MP_WAKEREQ);
+		lwkt_reltoken(&kpsus_token);
+		return(0);
+	} else {
+		return(EINVAL);	/* not a kernel thread */
+	}
+}
+
 void
 kproc_suspend_loop(void)
 {