summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2017-05-18 07:08:46 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2017-05-18 07:08:46 +0000
commit0fa1c0241b2e2aee5991c242ced52139edd081d6 (patch)
treecb33fb01f29a8b10c7dea5e7f6a8639f36cf73c7 /sys/kern
parent759d7a530ec4abbaa0343a71d209a313cb44f4e0 (diff)
Do not panic if we find ourself on the sleep queue while being SONPROC.
If the rwlock passed to rwsleep(9) is contented, the CPU will call wakeup() between sleep_setup() and sleep_finish(). At this moment curproc is on the sleep queue but marked as SONPROC. Avoid panicing in this case. Problem reported by sthen@ ok kettenis@, visa@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_synch.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c
index 9925025e304..83b4cc9f3b5 100644
--- a/sys/kern/kern_synch.c
+++ b/sys/kern/kern_synch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_synch.c,v 1.140 2017/04/20 13:57:30 visa Exp $ */
+/* $OpenBSD: kern_synch.c,v 1.141 2017/05/18 07:08:45 mpi Exp $ */
/* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
/*
@@ -450,6 +450,15 @@ wakeup_n(const volatile void *ident, int n)
for (p = TAILQ_FIRST(qp); p != NULL && n != 0; p = pnext) {
pnext = TAILQ_NEXT(p, p_runq);
#ifdef DIAGNOSTIC
+ /*
+ * If the rwlock passed to rwsleep() is contended, the
+ * CPU will end up calling wakeup() between sleep_setup()
+ * and sleep_finish().
+ */
+ if (p == curproc) {
+ KASSERT(p->p_stat == SONPROC);
+ continue;
+ }
if (p->p_stat != SSLEEP && p->p_stat != SSTOP)
panic("wakeup: p_stat is %d", (int)p->p_stat);
#endif