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 *);
 

Reply via email to