aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-09-05 18:30:34 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-10-11 21:39:27 -0400
commit6972d6f25d21e3da58ff1309256c787078405c7f (patch)
tree1492fa5424db7272573b2094522fc72f82974f40
parent7721d3c2083c27bfb8e4c1335d343e25ae1a663f (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>
-rw-r--r--arch/alpha/kernel/entry.S10
-rw-r--r--arch/alpha/kernel/signal.c27
2 files changed, 20 insertions, 17 deletions
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index 802108b15be8..0c30ccea9294 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 a8c97d42ec8e..235a8677eca8 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
570void 570void
571do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, 571do_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}