[PATCH 17/33] teach wake_up_quiescent() to do "selective" wake_up

Oleg Nesterov oleg at redhat.com
Mon Nov 21 20:02:12 UTC 2011


Both utrace and ptrace can want the same thread to be quiescent, in this
case its state is TASK_TRACED | TASK_UTRACED. And this also means that
this task must not run unless both utrace and ptrace resume it.

Change wake_up_quiescent(p, state) to do "p->state &= ~state" and return
false unless there is no more "quiescent" bits in task->state.

Signed-off-by: Oleg Nesterov <oleg at redhat.com>
---
 kernel/signal.c |   15 +++++++++++++++
 1 files changed, 15 insertions(+), 0 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index ba46eab..e06f795 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -701,11 +701,26 @@ void signal_wake_up(struct task_struct *t, int resume)
 		kick_process(t);
 }
 
+#define STATE_QUIESCENT	(__TASK_STOPPED | __TASK_TRACED | __TASK_UTRACED)
 /*
  * wakes up the STOPPED/TRACED task, must be called with ->siglock held.
  */
 int wake_up_quiescent(struct task_struct *p, unsigned int state)
 {
+	unsigned int quiescent = (p->state & STATE_QUIESCENT);
+
+	WARN_ON(state & ~(STATE_QUIESCENT | TASK_INTERRUPTIBLE));
+
+	if (quiescent) {
+		state &= ~TASK_INTERRUPTIBLE;
+		if ((quiescent & ~state) != 0) {
+			p->state &= ~state;
+			WARN_ON(!(p->state & STATE_QUIESCENT));
+			WARN_ON(!(p->state & TASK_WAKEKILL));
+			return 0;
+		}
+	}
+
 	return wake_up_state(p, state);
 }
 
-- 
1.5.5.1



More information about the kernel mailing list