diff options
author | Tejun Heo <tj@kernel.org> | 2011-06-02 05:14:00 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2011-06-04 12:17:11 -0400 |
commit | 62c124ff3bcdb414af635c2bf822c9e4f2a5abfa (patch) | |
tree | 5d279211e098d24245d49e394d84aa8cfdb6f277 /kernel | |
parent | 7dd3db54e77d21eb95e145f19ba53f68250d0e73 (diff) |
ptrace: use bit_waitqueue for TRAPPING instead of wait_chldexit
ptracer->signal->wait_chldexit was used to wait for TRAPPING; however,
->wait_chldexit was already complicated with waker-side filtering
without adding TRAPPING wait on top of it. Also, it unnecessarily
made TRAPPING clearing depend on the current ptrace relationship - if
the ptracee is detached, wakeup is lost.
There is no reason to use signal->wait_chldexit here. We're just
waiting for JOBCTL_TRAPPING bit to clear and given the relatively
infrequent use of ptrace, bit_waitqueue can serve it perfectly.
This patch makes JOBCTL_TRAPPING wait use bit_waitqueue instead of
signal->wait_chldexit.
-v2: Use JOBCTL_*_BIT macros instead of ilog2() as suggested by Linus.
Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/ptrace.c | 10 | ||||
-rw-r--r-- | kernel/signal.c | 3 |
2 files changed, 9 insertions, 4 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 0c37d999c8b8..7f05f3a1267b 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -25,6 +25,12 @@ | |||
25 | #include <linux/hw_breakpoint.h> | 25 | #include <linux/hw_breakpoint.h> |
26 | 26 | ||
27 | 27 | ||
28 | static int ptrace_trapping_sleep_fn(void *flags) | ||
29 | { | ||
30 | schedule(); | ||
31 | return 0; | ||
32 | } | ||
33 | |||
28 | /* | 34 | /* |
29 | * ptrace a task: make the debugger its new parent and | 35 | * ptrace a task: make the debugger its new parent and |
30 | * move it to the ptrace list. | 36 | * move it to the ptrace list. |
@@ -270,8 +276,8 @@ unlock_creds: | |||
270 | mutex_unlock(&task->signal->cred_guard_mutex); | 276 | mutex_unlock(&task->signal->cred_guard_mutex); |
271 | out: | 277 | out: |
272 | if (!retval) | 278 | if (!retval) |
273 | wait_event(current->signal->wait_chldexit, | 279 | wait_on_bit(&task->jobctl, JOBCTL_TRAPPING_BIT, |
274 | !(task->jobctl & JOBCTL_TRAPPING)); | 280 | ptrace_trapping_sleep_fn, TASK_UNINTERRUPTIBLE); |
275 | return retval; | 281 | return retval; |
276 | } | 282 | } |
277 | 283 | ||
diff --git a/kernel/signal.c b/kernel/signal.c index 9ab91c516c3f..172a4c79f12c 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -272,8 +272,7 @@ static void task_clear_jobctl_trapping(struct task_struct *task) | |||
272 | { | 272 | { |
273 | if (unlikely(task->jobctl & JOBCTL_TRAPPING)) { | 273 | if (unlikely(task->jobctl & JOBCTL_TRAPPING)) { |
274 | task->jobctl &= ~JOBCTL_TRAPPING; | 274 | task->jobctl &= ~JOBCTL_TRAPPING; |
275 | __wake_up_sync_key(&task->parent->signal->wait_chldexit, | 275 | wake_up_bit(&task->jobctl, JOBCTL_TRAPPING_BIT); |
276 | TASK_UNINTERRUPTIBLE, 1, task); | ||
277 | } | 276 | } |
278 | } | 277 | } |
279 | 278 | ||