Remove the assertion that `curproc' must be SONPROC if found on the sleepqueue.
authormpi <mpi@openbsd.org>
Thu, 7 Oct 2021 08:51:00 +0000 (08:51 +0000)
committermpi <mpi@openbsd.org>
Thu, 7 Oct 2021 08:51:00 +0000 (08:51 +0000)
If `curproc' finds itself on the sleepqueue inside wakeup(9) it is obviously
being executed.  Such wakeup(9) currently happens inside the critical section
of the SCHED_LOCK(), generally before cpu_switchto().  However `p_stat' is
changed many operations before cpu_switchto() and the KASSERT() isn't helpful
at catching real bugs.

One example of this is a call to rwsleep() that calls wakeup() via rw_exit()
before sleep_finish(), contented futex(2) triggers that a lot.

Another example are dt(4)'s scheduler TRACEPOINT() in setrunqueue() and
mi_switch().

Suggested by and ok kettenis@

sys/kern/kern_synch.c

index 511cfa8..f019026 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: kern_synch.c,v 1.179 2021/09/09 18:41:39 mpi Exp $    */
+/*     $OpenBSD: kern_synch.c,v 1.180 2021/10/07 08:51:00 mpi Exp $    */
 /*     $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */
 
 /*
@@ -558,14 +558,11 @@ 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);
                /*
-                * If the rwlock passed to rwsleep() is contended, the
-                * CPU will end up calling wakeup() between sleep_setup()
-                * and sleep_finish().
+                * This happens if wakeup(9) is called after enqueuing
+                * itself on the sleep queue and both `ident' collide.
                 */
-               if (p == curproc) {
-                       KASSERT(p->p_stat == SONPROC);
+               if (p == curproc)
                        continue;
-               }
 #ifdef DIAGNOSTIC
                if (p->p_stat != SSLEEP && p->p_stat != SSTOP)
                        panic("wakeup: p_stat is %d", (int)p->p_stat);