Hi, one step to (at some point) change the sched lock to a mutex is to start avoiding recursion on the sched lock.
single_thread_check() always takes the sched lock. If we want to avoid recursion, we need to call the locked version and take the sched lock ourselves if we need to. Another option might be to just put SCHED_LOCK()/SCHED_UNLOCK() around call to sleep_signal_check(), but then this might end up in future confusion if we ever wonder why we are taking the lock there in the first place. Opinions? Patrick diff --git a/sys/kern/kern_synch.c b/sys/kern/kern_synch.c index b476a6b4253..030b3a38326 100644 --- a/sys/kern/kern_synch.c +++ b/sys/kern/kern_synch.c @@ -66,6 +66,7 @@ #endif int sleep_signal_check(void); +int sleep_signal_check_locked(int s); int thrsleep(struct proc *, struct sys___thrsleep_args *); int thrsleep_unlock(void *); @@ -410,7 +411,7 @@ sleep_finish(struct sleep_state *sls, int do_sleep) * that case we need to unwind immediately. */ atomic_setbits_int(&p->p_flag, P_SINTR); - if ((error = sleep_signal_check()) != 0) { + if ((error = sleep_signal_check_locked(sls->sls_s)) != 0) { p->p_stat = SONPROC; sls->sls_catch = 0; do_sleep = 0; @@ -470,14 +471,30 @@ sleep_finish(struct sleep_state *sls, int do_sleep) /* * Check and handle signals and suspensions around a sleep cycle. + * + * single_thread_check() always takes the sched lock. To avoid + * recursion on the sched lock, call the locked version and take + * it ourselves if we need to. */ int sleep_signal_check(void) +{ + int err, s; + + SCHED_LOCK(s); + err = sleep_signal_check_locked(s); + SCHED_UNLOCK(s); + + return err; +} + +int +sleep_signal_check_locked(int s) { struct proc *p = curproc; int err, sig; - if ((err = single_thread_check(p, 1)) != 0) + if ((err = single_thread_check_locked(p, 1, s)) != 0) return err; if ((sig = cursig(p)) != 0) { if (p->p_p->ps_sigacts->ps_sigintr & sigmask(sig)) diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 4dbc097f242..978fd5632cd 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -605,6 +605,7 @@ int single_thread_set(struct proc *, enum single_thread_mode, int); int single_thread_wait(struct process *, int); void single_thread_clear(struct proc *, int); int single_thread_check(struct proc *, int); +int single_thread_check_locked(struct proc *, int, int); void child_return(void *);