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