Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Richard Henderson and committed by
Linus Torvalds
b927b3e2 74fd1b68

+147 -52
+3 -4
arch/alpha/kernel/entry.S
··· 391 391 bne $2, $work_resched 392 392 393 393 $work_notifysig: 394 - mov $sp, $17 394 + mov $sp, $16 395 395 br $1, do_switch_stack 396 - mov $5, $21 397 - mov $sp, $18 398 - mov $31, $16 396 + mov $sp, $17 397 + mov $5, $18 399 398 jsr $26, do_notify_resume 400 399 bsr $1, undo_switch_stack 401 400 br restore_all
+63 -47
arch/alpha/kernel/signal.c
··· 32 32 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 33 33 34 34 asmlinkage void ret_from_sys_call(void); 35 - static int do_signal(sigset_t *, struct pt_regs *, struct switch_stack *, 36 - unsigned long, unsigned long); 35 + static void do_signal(struct pt_regs *, struct switch_stack *, 36 + unsigned long, unsigned long); 37 37 38 38 39 39 /* ··· 146 146 asmlinkage int 147 147 do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw) 148 148 { 149 - sigset_t oldset; 150 - 151 149 mask &= _BLOCKABLE; 152 150 spin_lock_irq(&current->sighand->siglock); 153 - oldset = current->blocked; 151 + current->saved_sigmask = current->blocked; 154 152 siginitset(&current->blocked, mask); 155 153 recalc_sigpending(); 156 154 spin_unlock_irq(&current->sighand->siglock); ··· 158 160 regs->r0 = EINTR; 159 161 regs->r19 = 1; 160 162 161 - while (1) { 162 - current->state = TASK_INTERRUPTIBLE; 163 - schedule(); 164 - if (do_signal(&oldset, regs, sw, 0, 0)) 165 - return -EINTR; 166 - } 163 + current->state = TASK_INTERRUPTIBLE; 164 + schedule(); 165 + set_thread_flag(TIF_RESTORE_SIGMASK); 166 + return -ERESTARTNOHAND; 167 167 } 168 168 169 169 asmlinkage int 170 170 do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize, 171 171 struct pt_regs *regs, struct switch_stack *sw) 172 172 { 173 - sigset_t oldset, set; 173 + sigset_t set; 174 174 175 175 /* XXX: Don't preclude handling different sized sigset_t's. */ 176 176 if (sigsetsize != sizeof(sigset_t)) ··· 178 182 179 183 sigdelsetmask(&set, ~_BLOCKABLE); 180 184 spin_lock_irq(&current->sighand->siglock); 181 - oldset = current->blocked; 185 + current->saved_sigmask = current->blocked; 182 186 current->blocked = set; 183 187 recalc_sigpending(); 184 188 spin_unlock_irq(&current->sighand->siglock); ··· 188 192 regs->r0 = EINTR; 189 193 regs->r19 = 1; 190 194 191 - while (1) { 192 - current->state = TASK_INTERRUPTIBLE; 193 - schedule(); 194 - if (do_signal(&oldset, regs, sw, 0, 0)) 195 - return -EINTR; 196 - } 195 + current->state = TASK_INTERRUPTIBLE; 196 + schedule(); 197 + set_thread_flag(TIF_RESTORE_SIGMASK); 198 + return -ERESTARTNOHAND; 197 199 } 198 200 199 201 asmlinkage int ··· 430 436 return err; 431 437 } 432 438 433 - static void 439 + static int 434 440 setup_frame(int sig, struct k_sigaction *ka, sigset_t *set, 435 441 struct pt_regs *regs, struct switch_stack * sw) 436 442 { ··· 475 481 current->comm, current->pid, frame, regs->pc, regs->r26); 476 482 #endif 477 483 478 - return; 484 + return 0; 479 485 480 486 give_sigsegv: 481 487 force_sigsegv(sig, current); 488 + return -EFAULT; 482 489 } 483 490 484 - static void 491 + static int 485 492 setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 486 493 sigset_t *set, struct pt_regs *regs, struct switch_stack * sw) 487 494 { ··· 538 543 current->comm, current->pid, frame, regs->pc, regs->r26); 539 544 #endif 540 545 541 - return; 546 + return 0; 542 547 543 548 give_sigsegv: 544 549 force_sigsegv(sig, current); 550 + return -EFAULT; 545 551 } 546 552 547 553 548 554 /* 549 555 * OK, we're invoking a handler. 550 556 */ 551 - static inline void 557 + static inline int 552 558 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info, 553 559 sigset_t *oldset, struct pt_regs * regs, struct switch_stack *sw) 554 560 { 561 + int ret; 562 + 555 563 if (ka->sa.sa_flags & SA_SIGINFO) 556 - setup_rt_frame(sig, ka, info, oldset, regs, sw); 564 + ret = setup_rt_frame(sig, ka, info, oldset, regs, sw); 557 565 else 558 - setup_frame(sig, ka, oldset, regs, sw); 566 + ret = setup_frame(sig, ka, oldset, regs, sw); 559 567 560 - if (ka->sa.sa_flags & SA_RESETHAND) 561 - ka->sa.sa_handler = SIG_DFL; 568 + if (ret == 0) { 569 + spin_lock_irq(&current->sighand->siglock); 570 + sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 571 + if (!(ka->sa.sa_flags & SA_NODEFER)) 572 + sigaddset(&current->blocked,sig); 573 + recalc_sigpending(); 574 + spin_unlock_irq(&current->sighand->siglock); 575 + } 562 576 563 - spin_lock_irq(&current->sighand->siglock); 564 - sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask); 565 - if (!(ka->sa.sa_flags & SA_NODEFER)) 566 - sigaddset(&current->blocked,sig); 567 - recalc_sigpending(); 568 - spin_unlock_irq(&current->sighand->siglock); 577 + return ret; 569 578 } 570 579 571 580 static inline void ··· 610 611 * restart. "r0" is also used as an indicator whether we can restart at 611 612 * all (if we get here from anything but a syscall return, it will be 0) 612 613 */ 613 - static int 614 - do_signal(sigset_t *oldset, struct pt_regs * regs, struct switch_stack * sw, 614 + static void 615 + do_signal(struct pt_regs * regs, struct switch_stack * sw, 615 616 unsigned long r0, unsigned long r19) 616 617 { 617 618 siginfo_t info; 618 619 int signr; 619 620 unsigned long single_stepping = ptrace_cancel_bpt(current); 620 621 struct k_sigaction ka; 622 + sigset_t *oldset; 621 623 622 - if (!oldset) 624 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) 625 + oldset = &current->saved_sigmask; 626 + else 623 627 oldset = &current->blocked; 624 628 625 629 /* This lets the debugger run, ... */ 626 630 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 631 + 627 632 /* ... so re-check the single stepping. */ 628 633 single_stepping |= ptrace_cancel_bpt(current); 629 634 630 635 if (signr > 0) { 631 636 /* Whee! Actually deliver the signal. */ 632 - if (r0) syscall_restart(r0, r19, regs, &ka); 633 - handle_signal(signr, &ka, &info, oldset, regs, sw); 637 + if (r0) 638 + syscall_restart(r0, r19, regs, &ka); 639 + if (handle_signal(signr, &ka, &info, oldset, regs, sw) == 0) { 640 + /* A signal was successfully delivered, and the 641 + saved sigmask was stored on the signal frame, 642 + and will be restored by sigreturn. So we can 643 + simply clear the restore sigmask flag. */ 644 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) 645 + clear_thread_flag(TIF_RESTORE_SIGMASK); 646 + } 634 647 if (single_stepping) 635 648 ptrace_set_bpt(current); /* re-set bpt */ 636 - return 1; 649 + return; 637 650 } 638 651 639 652 if (r0) { ··· 665 654 break; 666 655 } 667 656 } 657 + 658 + /* If there's no signal to deliver, we just restore the saved mask. */ 659 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 660 + clear_thread_flag(TIF_RESTORE_SIGMASK); 661 + sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 662 + } 663 + 668 664 if (single_stepping) 669 665 ptrace_set_bpt(current); /* re-set breakpoint */ 670 - 671 - return 0; 672 666 } 673 667 674 668 void 675 - do_notify_resume(sigset_t *oldset, struct pt_regs *regs, 676 - struct switch_stack *sw, unsigned long r0, 677 - unsigned long r19, unsigned long thread_info_flags) 669 + do_notify_resume(struct pt_regs *regs, struct switch_stack *sw, 670 + unsigned long thread_info_flags, 671 + unsigned long r0, unsigned long r19) 678 672 { 679 - if (thread_info_flags & _TIF_SIGPENDING) 680 - do_signal(oldset, regs, sw, r0, r19); 673 + if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) 674 + do_signal(regs, sw, r0, r19); 681 675 }
+32
arch/alpha/kernel/systbls.S
··· 465 465 .quad sys_inotify_init 466 466 .quad sys_inotify_add_watch /* 445 */ 467 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 501 .size sys_call_table, . - sys_call_table 470 502 .type sys_call_table, @object
+2
include/asm-alpha/thread_info.h
··· 76 76 #define TIF_UAC_NOFIX 7 77 77 #define TIF_UAC_SIGBUS 8 78 78 #define TIF_MEMDIE 9 79 + #define TIF_RESTORE_SIGMASK 10 /* restore signal mask in do_signal */ 79 80 80 81 #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 81 82 #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) 82 83 #define _TIF_SIGPENDING (1<<TIF_SIGPENDING) 83 84 #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) 84 85 #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) 86 + #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) 85 87 86 88 /* Work to do on interrupt/exception return. */ 87 89 #define _TIF_WORK_MASK (_TIF_NOTIFY_RESUME \
+47 -1
include/asm-alpha/unistd.h
··· 233 233 #define __NR_osf_memcntl 260 /* not implemented */ 234 234 #define __NR_osf_fdatasync 261 /* not implemented */ 235 235 236 + /* 237 + * Ignore legacy syscalls that we don't use. 238 + */ 239 + #define __IGNORE_alarm 240 + #define __IGNORE_creat 241 + #define __IGNORE_getegid 242 + #define __IGNORE_geteuid 243 + #define __IGNORE_getgid 244 + #define __IGNORE_getpid 245 + #define __IGNORE_getppid 246 + #define __IGNORE_getuid 247 + #define __IGNORE_pause 248 + #define __IGNORE_time 249 + #define __IGNORE_utime 236 250 237 251 /* 238 252 * Linux-specific system calls begin at 300 ··· 401 387 #define __NR_inotify_init 444 402 388 #define __NR_inotify_add_watch 445 403 389 #define __NR_inotify_rm_watch 446 390 + #define __NR_fdatasync 447 391 + #define __NR_kexec_load 448 392 + #define __NR_migrate_pages 449 393 + #define __NR_openat 450 394 + #define __NR_mkdirat 451 395 + #define __NR_mknodat 452 396 + #define __NR_fchownat 453 397 + #define __NR_futimesat 454 398 + #define __NR_fstatat64 455 399 + #define __NR_unlinkat 456 400 + #define __NR_renameat 457 401 + #define __NR_linkat 458 402 + #define __NR_symlinkat 459 403 + #define __NR_readlinkat 460 404 + #define __NR_fchmodat 461 405 + #define __NR_faccessat 462 406 + #define __NR_pselect6 463 407 + #define __NR_ppoll 464 408 + #define __NR_unshare 465 409 + #define __NR_set_robust_list 466 410 + #define __NR_get_robust_list 467 411 + #define __NR_splice 468 412 + #define __NR_sync_file_range 469 413 + #define __NR_tee 470 414 + #define __NR_vmsplice 471 415 + #define __NR_move_pages 472 416 + #define __NR_getcpu 473 417 + #define __NR_epoll_pwait 474 418 + #define __NR_utimensat 475 419 + #define __NR_signalfd 476 420 + #define __NR_timerfd 477 421 + #define __NR_eventfd 478 404 422 405 423 #ifdef __KERNEL__ 406 424 407 - #define NR_SYSCALLS 447 425 + #define NR_SYSCALLS 479 408 426 409 427 #define __ARCH_WANT_IPC_PARSE_VERSION 410 428 #define __ARCH_WANT_OLD_READDIR