From 94d095245c11f208cc49d2676db5810a57239c67 Mon Sep 17 00:00:00 2001 From: Oleg Nesterov Date: Tue, 28 Mar 2006 16:11:22 -0800 Subject: [PATCH] --- yaml --- r: 24567 b: refs/heads/master c: a122b341b74c08020f6521b615acca6a692aac79 h: refs/heads/master i: 24565: 50e56cb434f97d05cb2fe1a93f4ea96ac2045628 24563: f196a205c47108e328c1e2eb88fa188552543602 24559: dfa9166c19c75a5bfcc952ff7434c2be5dafe500 v: v3 --- [refs] | 2 +- trunk/kernel/signal.c | 69 +++++++++++-------------------------------- 2 files changed, 18 insertions(+), 53 deletions(-) diff --git a/[refs] b/[refs] index 1271e661ddfa..50cc1ef0750a 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 6108ccd3e2f3012d5eec582e0af4d75e693824da +refs/heads/master: a122b341b74c08020f6521b615acca6a692aac79 diff --git a/trunk/kernel/signal.c b/trunk/kernel/signal.c index e99ec2f891a0..e3bdec914626 100644 --- a/trunk/kernel/signal.c +++ b/trunk/kernel/signal.c @@ -1682,8 +1682,7 @@ finish_stop(int stop_count) * Returns nonzero if we've actually stopped and released the siglock. * Returns zero if we didn't stop and still hold the siglock. */ -static int -do_signal_stop(int signr) +static int do_signal_stop(int signr) { struct signal_struct *sig = current->signal; struct sighand_struct *sighand = current->sighand; @@ -1703,7 +1702,6 @@ do_signal_stop(int signr) set_current_state(TASK_STOPPED); if (stop_count == 0) sig->flags = SIGNAL_STOP_STOPPED; - spin_unlock_irq(&sighand->siglock); } else if (thread_group_empty(current)) { /* @@ -1712,71 +1710,38 @@ do_signal_stop(int signr) current->exit_code = current->signal->group_exit_code = signr; set_current_state(TASK_STOPPED); sig->flags = SIGNAL_STOP_STOPPED; - spin_unlock_irq(&sighand->siglock); } else { /* + * (sig->group_stop_count == 0) * There is no group stop already in progress. - * We must initiate one now, but that requires - * dropping siglock to get both the tasklist lock - * and siglock again in the proper order. Note that - * this allows an intervening SIGCONT to be posted. - * We need to check for that and bail out if necessary. + * We must initiate one now. */ struct task_struct *t; - spin_unlock_irq(&sighand->siglock); - - /* signals can be posted during this window */ - - read_lock(&tasklist_lock); - spin_lock_irq(&sighand->siglock); + current->exit_code = signr; + sig->group_exit_code = signr; - if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED)) { + stop_count = 0; + for (t = next_thread(current); t != current; t = next_thread(t)) /* - * Another stop or continue happened while we - * didn't have the lock. We can just swallow this - * signal now. If we raced with a SIGCONT, that - * should have just cleared it now. If we raced - * with another processor delivering a stop signal, - * then the SIGCONT that wakes us up should clear it. + * Setting state to TASK_STOPPED for a group + * stop is always done with the siglock held, + * so this check has no races. */ - read_unlock(&tasklist_lock); - return 0; - } - - if (sig->group_stop_count == 0) { - sig->group_exit_code = signr; - stop_count = 0; - for (t = next_thread(current); t != current; - t = next_thread(t)) - /* - * Setting state to TASK_STOPPED for a group - * stop is always done with the siglock held, - * so this check has no races. - */ - if (!t->exit_state && - !(t->state & (TASK_STOPPED|TASK_TRACED))) { - stop_count++; - signal_wake_up(t, 0); - } - sig->group_stop_count = stop_count; - } - else { - /* A race with another thread while unlocked. */ - signr = sig->group_exit_code; - stop_count = --sig->group_stop_count; - } + if (!t->exit_state && + !(t->state & (TASK_STOPPED|TASK_TRACED))) { + stop_count++; + signal_wake_up(t, 0); + } + sig->group_stop_count = stop_count; - current->exit_code = signr; set_current_state(TASK_STOPPED); if (stop_count == 0) sig->flags = SIGNAL_STOP_STOPPED; - - spin_unlock_irq(&sighand->siglock); - read_unlock(&tasklist_lock); } + spin_unlock_irq(&sighand->siglock); finish_stop(stop_count); return 1; }