aboutsummaryrefslogtreecommitdiffstats
path: root/arch/alpha
diff options
context:
space:
mode:
authorRichard Henderson <rth@twiddle.net>2007-05-29 19:03:28 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-30 13:07:54 -0400
commitb927b3e2c9bc39b7eeeaca91e4cd6c3ed59f165a (patch)
treeabdb72c2f2b8ab6cfaa954b558e8c078d04d1a85 /arch/alpha
parent74fd1b687fbeba566ceb59cc1fdbc7a64c5e0c0b (diff)
alpha: support new syscalls
Some of the new syscalls require supporting TIF_RESTORE_SIGMASK. Signed-off-by: Richard Henderson <rth@twiddle.net> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/alpha')
-rw-r--r--arch/alpha/kernel/entry.S7
-rw-r--r--arch/alpha/kernel/signal.c110
-rw-r--r--arch/alpha/kernel/systbls.S32
3 files changed, 98 insertions, 51 deletions
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S
index c95e95e1ab04..debc8f03886c 100644
--- a/arch/alpha/kernel/entry.S
+++ b/arch/alpha/kernel/entry.S
@@ -391,11 +391,10 @@ $work_resched:
391 bne $2, $work_resched 391 bne $2, $work_resched
392 392
393$work_notifysig: 393$work_notifysig:
394 mov $sp, $17 394 mov $sp, $16
395 br $1, do_switch_stack 395 br $1, do_switch_stack
396 mov $5, $21 396 mov $sp, $17
397 mov $sp, $18 397 mov $5, $18
398 mov $31, $16
399 jsr $26, do_notify_resume 398 jsr $26, do_notify_resume
400 bsr $1, undo_switch_stack 399 bsr $1, undo_switch_stack
401 br restore_all 400 br restore_all
diff --git a/arch/alpha/kernel/signal.c b/arch/alpha/kernel/signal.c
index 7f64aa767d5a..410af4f3140e 100644
--- a/arch/alpha/kernel/signal.c
+++ b/arch/alpha/kernel/signal.c
@@ -32,8 +32,8 @@
32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 32#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
33 33
34asmlinkage void ret_from_sys_call(void); 34asmlinkage void ret_from_sys_call(void);
35static int do_signal(sigset_t *, struct pt_regs *, struct switch_stack *, 35static void do_signal(struct pt_regs *, struct switch_stack *,
36 unsigned long, unsigned long); 36 unsigned long, unsigned long);
37 37
38 38
39/* 39/*
@@ -146,11 +146,9 @@ sys_rt_sigaction(int sig, const struct sigaction __user *act,
146asmlinkage int 146asmlinkage int
147do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) 147do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
148{ 148{
149 sigset_t oldset;
150
151 mask &= _BLOCKABLE; 149 mask &= _BLOCKABLE;
152 spin_lock_irq(&current->sighand->siglock); 150 spin_lock_irq(&current->sighand->siglock);
153 oldset = current->blocked; 151 current->saved_sigmask = current->blocked;
154 siginitset(&current->blocked, mask); 152 siginitset(&current->blocked, mask);
155 recalc_sigpending(); 153 recalc_sigpending();
156 spin_unlock_irq(&current->sighand->siglock); 154 spin_unlock_irq(&current->sighand->siglock);
@@ -160,19 +158,17 @@ do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
160 regs->r0 = EINTR; 158 regs->r0 = EINTR;
161 regs->r19 = 1; 159 regs->r19 = 1;
162 160
163 while (1) { 161 current->state = TASK_INTERRUPTIBLE;
164 current->state = TASK_INTERRUPTIBLE; 162 schedule();
165 schedule(); 163 set_thread_flag(TIF_RESTORE_SIGMASK);
166 if (do_signal(&oldset, regs, sw, 0, 0)) 164 return -ERESTARTNOHAND;
167 return -EINTR;
168 }
169} 165}
170 166
171asmlinkage int 167asmlinkage int
172do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, 168do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
173 struct pt_regs *regs, struct switch_stack *sw) 169 struct pt_regs *regs, struct switch_stack *sw)
174{ 170{
175 sigset_t oldset, set; 171 sigset_t set;
176 172
177 /* XXX: Don't preclude handling different sized sigset_t's. */ 173 /* XXX: Don't preclude handling different sized sigset_t's. */
178 if (sigsetsize != sizeof(sigset_t)) 174 if (sigsetsize != sizeof(sigset_t))
@@ -182,7 +178,7 @@ do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
182 178
183 sigdelsetmask(&set, ~_BLOCKABLE); 179 sigdelsetmask(&set, ~_BLOCKABLE);
184 spin_lock_irq(&current->sighand->siglock); 180 spin_lock_irq(&current->sighand->siglock);
185 oldset = current->blocked; 181 current->saved_sigmask = current->blocked;
186 current->blocked = set; 182 current->blocked = set;
187 recalc_sigpending(); 183 recalc_sigpending();
188 spin_unlock_irq(&current->sighand->siglock); 184 spin_unlock_irq(&current->sighand->siglock);
@@ -192,12 +188,10 @@ do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
192 regs->r0 = EINTR; 188 regs->r0 = EINTR;
193 regs->r19 = 1; 189 regs->r19 = 1;
194 190
195 while (1) { 191 current->state = TASK_INTERRUPTIBLE;
196 current->state = TASK_INTERRUPTIBLE; 192 schedule();
197 schedule(); 193 set_thread_flag(TIF_RESTORE_SIGMASK);
198 if (do_signal(&oldset, regs, sw, 0, 0)) 194 return -ERESTARTNOHAND;
199 return -EINTR;
200 }
201} 195}
202 196
203asmlinkage int 197asmlinkage int
@@ -436,7 +430,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
436 return err; 430 return err;
437} 431}
438 432
439static void 433static int
440setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, 434setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
441 struct pt_regs *regs, struct switch_stack * sw) 435 struct pt_regs *regs, struct switch_stack * sw)
442{ 436{
@@ -481,13 +475,14 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
481 current->comm, current->pid, frame, regs->pc, regs->r26); 475 current->comm, current->pid, frame, regs->pc, regs->r26);
482#endif 476#endif
483 477
484 return; 478 return 0;
485 479
486give_sigsegv: 480give_sigsegv:
487 force_sigsegv(sig, current); 481 force_sigsegv(sig, current);
482 return -EFAULT;
488} 483}
489 484
490static void 485static int
491setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 486setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
492 sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) 487 sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
493{ 488{
@@ -543,34 +538,38 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
543 current->comm, current->pid, frame, regs->pc, regs->r26); 538 current->comm, current->pid, frame, regs->pc, regs->r26);
544#endif 539#endif
545 540
546 return; 541 return 0;
547 542
548give_sigsegv: 543give_sigsegv:
549 force_sigsegv(sig, current); 544 force_sigsegv(sig, current);
545 return -EFAULT;
550} 546}
551 547
552 548
553/* 549/*
554 * OK, we're invoking a handler. 550 * OK, we're invoking a handler.
555 */ 551 */
556static inline void 552static inline int
557handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 553handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
558 sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) 554 sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw)
559{ 555{
556 int ret;
557
560 if (ka->sa.sa_flags & SA_SIGINFO) 558 if (ka->sa.sa_flags & SA_SIGINFO)
561 setup_rt_frame(sig, ka, info, oldset, regs, sw); 559 ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
562 else 560 else
563 setup_frame(sig, ka, oldset, regs, sw); 561 ret = setup_frame(sig, ka, oldset, regs, sw);
564 562
565 if (ka->sa.sa_flags & SA_RESETHAND) 563 if (ret == 0) {
566 ka->sa.sa_handler = SIG_DFL; 564 spin_lock_irq(&current->sighand->siglock);
565 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
566 if (!(ka->sa.sa_flags & SA_NODEFER))
567 sigaddset(&current->blocked,sig);
568 recalc_sigpending();
569 spin_unlock_irq(&current->sighand->siglock);
570 }
567 571
568 spin_lock_irq(&current->sighand->siglock); 572 return ret;
569 sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
570 if (!(ka->sa.sa_flags & SA_NODEFER))
571 sigaddset(&current->blocked,sig);
572 recalc_sigpending();
573 spin_unlock_irq(&current->sighand->siglock);
574} 573}
575 574
576static inline void 575static inline void
@@ -611,30 +610,42 @@ syscall_restart(unsigned long r0, unsigned long r19,
611 * restart. "r0" is also used as an indicator whether we can restart at 610 * restart. "r0" is also used as an indicator whether we can restart at
612 * all (if we get here from anything but a syscall return, it will be 0) 611 * all (if we get here from anything but a syscall return, it will be 0)
613 */ 612 */
614static int 613static void
615do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, 614do_signal(struct pt_regs * regs, struct switch_stack * sw,
616 unsigned long r0, unsigned long r19) 615 unsigned long r0, unsigned long r19)
617{ 616{
618 siginfo_t info; 617 siginfo_t info;
619 int signr; 618 int signr;
620 unsigned long single_stepping = ptrace_cancel_bpt(current); 619 unsigned long single_stepping = ptrace_cancel_bpt(current);
621 struct k_sigaction ka; 620 struct k_sigaction ka;
621 sigset_t *oldset;
622 622
623 if (!oldset) 623 if (test_thread_flag(TIF_RESTORE_SIGMASK))
624 oldset = &current->saved_sigmask;
625 else
624 oldset = &current->blocked; 626 oldset = &current->blocked;
625 627
626 /* This lets the debugger run, ... */ 628 /* This lets the debugger run, ... */
627 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 629 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
630
628 /* ... so re-check the single stepping. */ 631 /* ... so re-check the single stepping. */
629 single_stepping |= ptrace_cancel_bpt(current); 632 single_stepping |= ptrace_cancel_bpt(current);
630 633
631 if (signr > 0) { 634 if (signr > 0) {
632 /* Whee! Actually deliver the signal. */ 635 /* Whee! Actually deliver the signal. */
633 if (r0) syscall_restart(r0, r19, regs, &ka); 636 if (r0)
634 handle_signal(signr, &ka, &info, oldset, regs, sw); 637 syscall_restart(r0, r19, regs, &ka);
638 if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) {
639 /* A signal was successfully delivered, and the
640 saved sigmask was stored on the signal frame,
641 and will be restored by sigreturn. So we can
642 simply clear the restore sigmask flag. */
643 if (test_thread_flag(TIF_RESTORE_SIGMASK))
644 clear_thread_flag(TIF_RESTORE_SIGMASK);
645 }
635 if (single_stepping) 646 if (single_stepping)
636 ptrace_set_bpt(current); /* re-set bpt */ 647 ptrace_set_bpt(current); /* re-set bpt */
637 return 1; 648 return;
638 } 649 }
639 650
640 if (r0) { 651 if (r0) {
@@ -654,17 +665,22 @@ do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw,
654 break; 665 break;
655 } 666 }
656 } 667 }
668
669 /* If there's no signal to deliver, we just restore the saved mask. */
670 if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
671 clear_thread_flag(TIF_RESTORE_SIGMASK);
672 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
673 }
674
657 if (single_stepping) 675 if (single_stepping)
658 ptrace_set_bpt(current); /* re-set breakpoint */ 676 ptrace_set_bpt(current); /* re-set breakpoint */
659
660 return 0;
661} 677}
662 678
663void 679void
664do_notify_resume(sigset_t *oldset, struct pt_regs *regs, 680do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
665 struct switch_stack *sw, unsigned long r0, 681 unsigned long thread_info_flags,
666 unsigned long r19, unsigned long thread_info_flags) 682 unsigned long r0, unsigned long r19)
667{ 683{
668 if (thread_info_flags & _TIF_SIGPENDING) 684 if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
669 do_signal(oldset, regs, sw, r0, r19); 685 do_signal(regs, sw, r0, r19);
670} 686}
diff --git a/arch/alpha/kernel/systbls.S b/arch/alpha/kernel/systbls.S
index f6cfe8ce3f96..79de99e32c35 100644
--- a/arch/alpha/kernel/systbls.S
+++ b/arch/alpha/kernel/systbls.S
@@ -465,6 +465,38 @@ sys_call_table:
465 .quad sys_inotify_init 465 .quad sys_inotify_init
466 .quad sys_inotify_add_watch /* 445 */ 466 .quad sys_inotify_add_watch /* 445 */
467 .quad sys_inotify_rm_watch 467 .quad sys_inotify_rm_watch
468 .quad sys_fdatasync
469 .quad sys_kexec_load
470 .quad sys_migrate_pages
471 .quad sys_openat /* 450 */
472 .quad sys_mkdirat
473 .quad sys_mknodat
474 .quad sys_fchownat
475 .quad sys_futimesat
476 .quad sys_fstatat64 /* 455 */
477 .quad sys_unlinkat
478 .quad sys_renameat
479 .quad sys_linkat
480 .quad sys_symlinkat
481 .quad sys_readlinkat /* 460 */
482 .quad sys_fchmodat
483 .quad sys_faccessat
484 .quad sys_pselect6
485 .quad sys_ppoll
486 .quad sys_unshare /* 465 */
487 .quad sys_set_robust_list
488 .quad sys_get_robust_list
489 .quad sys_splice
490 .quad sys_sync_file_range
491 .quad sys_tee /* 470 */
492 .quad sys_vmsplice
493 .quad sys_move_pages
494 .quad sys_getcpu
495 .quad sys_epoll_pwait
496 .quad sys_utimensat /* 475 */
497 .quad sys_signalfd
498 .quad sys_timerfd
499 .quad sys_eventfd
468 500
469 .size sys_call_table, . - sys_call_table 501 .size sys_call_table, . - sys_call_table
470 .type sys_call_table, @object 502 .type sys_call_table, @object