No functional changes. Add the new helper, wake_up_quiescent(task, state), which simply returns wake_up_state(task, state). Change all callers which do wake_up_state(STOPPED/TRACED) to use the new helper. ptrace_stop() is a bit special, it does __set_current_state(RUNNING) in the very unlikely case, change it as well.
Signed-off-by: Oleg Nesterov <o...@redhat.com> --- include/linux/signal.h | 2 ++ kernel/ptrace.c | 2 +- kernel/signal.c | 12 ++++++++++-- kernel/utrace.c | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/include/linux/signal.h b/include/linux/signal.h index a822300..2be3712 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -239,6 +239,8 @@ static inline int valid_signal(unsigned long sig) struct timespec; struct pt_regs; +extern int wake_up_quiescent(struct task_struct *p, unsigned int state); + extern int next_signal(struct sigpending *pending, sigset_t *mask); extern int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, bool group); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 9988b13..26ae214 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -566,7 +566,7 @@ static int ptrace_resume(struct task_struct *child, long request, child->exit_code = data; if (lock_task_sighand(child, &flags)) { - wake_up_state(child, __TASK_TRACED); + wake_up_quiescent(child, __TASK_TRACED); unlock_task_sighand(child, &flags); } diff --git a/kernel/signal.c b/kernel/signal.c index 2138cee..4fcf1c7 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -652,6 +652,14 @@ void signal_wake_up(struct task_struct *t, int resume) } /* + * wakes up the STOPPED/TRACED task, must be called with ->siglock held. + */ +int wake_up_quiescent(struct task_struct *p, unsigned int state) +{ + return wake_up_state(p, state); +} + +/* * Remove signals in mask from the pending set and queue. * Returns 1 if any signals were found. * @@ -811,7 +819,7 @@ static int prepare_signal(int sig, struct task_struct *p, int from_ancestor_ns) do { task_clear_group_stop_pending(t); rm_from_queue(SIG_KERNEL_STOP_MASK, &t->pending); - wake_up_state(t, __TASK_STOPPED); + wake_up_quiescent(t, __TASK_STOPPED); } while_each_thread(p, t); /* @@ -1800,7 +1808,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info) do_notify_parent_cldstop(current, false, why); spin_lock_irq(¤t->sighand->siglock); - __set_current_state(TASK_RUNNING); + wake_up_quiescent(current, __TASK_TRACED); spin_unlock_irq(¤t->sighand->siglock); if (clear_code) diff --git a/kernel/utrace.c b/kernel/utrace.c index 6e7fafb..d7c547c 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -648,7 +648,7 @@ static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) { lockdep_assert_held(&utrace->lock); spin_lock_irq(&target->sighand->siglock); - wake_up_state(target, __TASK_TRACED); + wake_up_quiescent(target, __TASK_TRACED); spin_unlock_irq(&target->sighand->siglock); } -- 1.5.5.1