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 <oleg(a)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