diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-05 18:30:34 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-11 21:39:27 -0400 |
| commit | 6972d6f25d21e3da58ff1309256c787078405c7f (patch) | |
| tree | 1492fa5424db7272573b2094522fc72f82974f40 /arch/alpha/kernel | |
| parent | 7721d3c2083c27bfb8e4c1335d343e25ae1a663f (diff) | |
alpha: take SIGPENDING/NOTIFY_RESUME loop into signal.c
Turn the slow side of work_pending into C function, including all
the looping. What we get out of that:
* we do _not_ call get_signal_to_deliver() with IRQs disabled
anymore
* no need to save/restore volatiles on each pass if there
turns to be more than one (unlikely, but still)
* all double-restart prevention is in C now.
* glue gets simpler.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/alpha/kernel')
| -rw-r--r-- | arch/alpha/kernel/entry.S | 10 | ||||
| -rw-r--r-- | arch/alpha/kernel/signal.c | 27 |
2 files changed, 20 insertions, 17 deletions
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index 802108b15be..0c30ccea929 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S | |||
| @@ -390,15 +390,9 @@ $work_notifysig: | |||
| 390 | bsr $1, do_switch_stack | 390 | bsr $1, do_switch_stack |
| 391 | mov $sp, $17 | 391 | mov $sp, $17 |
| 392 | mov $5, $18 | 392 | mov $5, $18 |
| 393 | mov $19, $9 /* save old syscall number */ | 393 | jsr $26, do_work_pending |
| 394 | mov $20, $10 /* save old a3 */ | ||
| 395 | and $5, _TIF_SIGPENDING, $2 | ||
| 396 | cmovne $2, 0, $9 /* we don't want double syscall restarts */ | ||
| 397 | jsr $26, do_notify_resume | ||
| 398 | mov $9, $19 | ||
| 399 | mov $10, $20 | ||
| 400 | bsr $1, undo_switch_stack | 394 | bsr $1, undo_switch_stack |
| 401 | br ret_to_user | 395 | br restore_all |
| 402 | .end work_pending | 396 | .end work_pending |
| 403 | 397 | ||
| 404 | /* | 398 | /* |
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c index a8c97d42ec8..235a8677eca 100644 --- a/arch/alpha/kernel/signal.c +++ b/arch/alpha/kernel/signal.c | |||
| @@ -568,15 +568,24 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw, | |||
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | void | 570 | void |
| 571 | do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, | 571 | do_work_pending(struct pt_regs *regs, struct switch_stack *sw, |
| 572 | unsigned long thread_info_flags, | 572 | unsigned long thread_flags, |
| 573 | unsigned long r0, unsigned long r19) | 573 | unsigned long r0, unsigned long r19) |
| 574 | { | 574 | { |
| 575 | if (thread_info_flags & _TIF_SIGPENDING) | 575 | do { |
| 576 | do_signal(regs, sw, r0, r19); | 576 | if (thread_flags & _TIF_NEED_RESCHED) { |
| 577 | 577 | schedule(); | |
| 578 | if (thread_info_flags & _TIF_NOTIFY_RESUME) { | 578 | } else { |
| 579 | clear_thread_flag(TIF_NOTIFY_RESUME); | 579 | local_irq_enable(); |
| 580 | tracehook_notify_resume(regs); | 580 | if (thread_flags & _TIF_SIGPENDING) { |
| 581 | } | 581 | do_signal(regs, sw, r0, r19); |
| 582 | r0 = 0; | ||
| 583 | } else { | ||
| 584 | clear_thread_flag(TIF_NOTIFY_RESUME); | ||
| 585 | tracehook_notify_resume(regs); | ||
| 586 | } | ||
| 587 | } | ||
| 588 | local_irq_disable(); | ||
| 589 | thread_flags = current_thread_info()->flags; | ||
| 590 | } while (thread_flags & _TIF_WORK_MASK); | ||
| 582 | } | 591 | } |
