diff --git a/sys/kern/kern_switch.c b/sys/kern/kern_switch.c index 68b6bc230081..b337e9da7dad 100644 --- a/sys/kern/kern_switch.c +++ b/sys/kern/kern_switch.c @@ -584,6 +584,10 @@ critical_exit(void) KASSERT(td->td_critnest != 0, ("critical_exit: td_critnest == 0")); if (td->td_critnest == 1) { + if (td->td_pflags & TDP_WAKEPROC0) { + td->td_pflags &= ~TDP_WAKEPROC0; + wakeup(&proc0); + } #ifdef PREEMPTION mtx_assert(&sched_lock, MA_NOTOWNED); if (td->td_pflags & TDP_OWEPREEMPT) { diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index d67887a2f56f..690dc9a2962a 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -391,13 +391,13 @@ setrunnable(struct thread *td) if ((p->p_sflag & PS_INMEM) == 0) { if ((p->p_sflag & PS_SWAPPINGIN) == 0) { p->p_sflag |= PS_SWAPINREQ; -#ifndef SMP /* - * XXX: Disabled on SMP due to a LOR between - * sched_lock and the sleepqueue chain locks. + * due to a LOR between sched_lock and + * the sleepqueue chain locks, delay + * wakeup proc0 until thread leaves + * critical region. */ - wakeup(&proc0); -#endif + curthread->td_pflags |= TDP_WAKEPROC0; } } else sched_wakeup(td); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index cd00c20e7e83..25d33c9d40cc 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -369,7 +369,7 @@ struct thread { #define TDP_SA 0x00000080 /* A scheduler activation based thread. */ #define TDP_OWEPREEMPT 0x00000100 /* Thread has a pending preemption. */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ -#define TDP_UNUSED10 0x00000400 /* -- available-- */ +#define TDP_WAKEPROC0 0x00000400 /* Wants caller to wakeup(&proc0) */ #define TDP_CAN_UNBIND 0x00000800 /* Only temporarily bound. */ #define TDP_SCHED1 0x00001000 /* Reserved for scheduler private use */ #define TDP_SCHED2 0x00002000 /* Reserved for scheduler private use */