提交 a122b341 编写于 作者: O Oleg Nesterov 提交者: Linus Torvalds

[PATCH] do_signal_stop: don't take tasklist_lock

do_signal_stop() does not need tasklist_lock anymore.  So it does not need to
do misc re-checks, and we can simplify the code.
Signed-off-by: NOleg Nesterov <oleg@tv-sign.ru>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 6108ccd3
...@@ -1682,8 +1682,7 @@ finish_stop(int stop_count) ...@@ -1682,8 +1682,7 @@ finish_stop(int stop_count)
* Returns nonzero if we've actually stopped and released the siglock. * Returns nonzero if we've actually stopped and released the siglock.
* Returns zero if we didn't stop and still hold the siglock. * Returns zero if we didn't stop and still hold the siglock.
*/ */
static int static int do_signal_stop(int signr)
do_signal_stop(int signr)
{ {
struct signal_struct *sig = current->signal; struct signal_struct *sig = current->signal;
struct sighand_struct *sighand = current->sighand; struct sighand_struct *sighand = current->sighand;
...@@ -1703,7 +1702,6 @@ do_signal_stop(int signr) ...@@ -1703,7 +1702,6 @@ do_signal_stop(int signr)
set_current_state(TASK_STOPPED); set_current_state(TASK_STOPPED);
if (stop_count == 0) if (stop_count == 0)
sig->flags = SIGNAL_STOP_STOPPED; sig->flags = SIGNAL_STOP_STOPPED;
spin_unlock_irq(&sighand->siglock);
} }
else if (thread_group_empty(current)) { else if (thread_group_empty(current)) {
/* /*
...@@ -1712,71 +1710,38 @@ do_signal_stop(int signr) ...@@ -1712,71 +1710,38 @@ do_signal_stop(int signr)
current->exit_code = current->signal->group_exit_code = signr; current->exit_code = current->signal->group_exit_code = signr;
set_current_state(TASK_STOPPED); set_current_state(TASK_STOPPED);
sig->flags = SIGNAL_STOP_STOPPED; sig->flags = SIGNAL_STOP_STOPPED;
spin_unlock_irq(&sighand->siglock);
} }
else { else {
/* /*
* (sig->group_stop_count == 0)
* There is no group stop already in progress. * There is no group stop already in progress.
* We must initiate one now, but that requires * We must initiate one now.
* 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.
*/ */
struct task_struct *t; struct task_struct *t;
spin_unlock_irq(&sighand->siglock); current->exit_code = signr;
sig->group_exit_code = signr;
/* signals can be posted during this window */
read_lock(&tasklist_lock);
spin_lock_irq(&sighand->siglock);
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 * Setting state to TASK_STOPPED for a group
* didn't have the lock. We can just swallow this * stop is always done with the siglock held,
* signal now. If we raced with a SIGCONT, that * so this check has no races.
* 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.
*/ */
read_unlock(&tasklist_lock); if (!t->exit_state &&
return 0; !(t->state & (TASK_STOPPED|TASK_TRACED))) {
} stop_count++;
signal_wake_up(t, 0);
if (sig->group_stop_count == 0) { }
sig->group_exit_code = signr; sig->group_stop_count = stop_count;
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;
}
current->exit_code = signr;
set_current_state(TASK_STOPPED); set_current_state(TASK_STOPPED);
if (stop_count == 0) if (stop_count == 0)
sig->flags = SIGNAL_STOP_STOPPED; sig->flags = SIGNAL_STOP_STOPPED;
spin_unlock_irq(&sighand->siglock);
read_unlock(&tasklist_lock);
} }
spin_unlock_irq(&sighand->siglock);
finish_stop(stop_count); finish_stop(stop_count);
return 1; return 1;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册