diff options
author | Alexey Dobriyan <adobriyan@openvz.org> | 2007-01-23 11:03:17 -0500 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2007-05-08 17:51:59 -0400 |
commit | 4a177cbf84f827cf9f1d6cfa5264fafd3cc33ce0 (patch) | |
tree | ef04ada4e2b708ee965081cd905026c9156863d3 /arch/ia64 | |
parent | 690def21414fa43fac1b8053fd952c0366c476de (diff) |
[IA64] Add TIF_RESTORE_SIGMASK
Preparation for pselect and ppoll.
ia32 compat code not tested. :-(
Signed-off-by: Alexey Kuznetsov <kuznet@ms2.inr.ac.ru>
Signed-off-by: Alexey Dobriyan <adobriyan@openvz.org>
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/ia32/ia32_entry.S | 39 | ||||
-rw-r--r-- | arch/ia64/ia32/ia32_signal.c | 59 | ||||
-rw-r--r-- | arch/ia64/kernel/entry.S | 26 | ||||
-rw-r--r-- | arch/ia64/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/ia64/kernel/sigframe.h | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/signal.c | 71 |
6 files changed, 38 insertions, 165 deletions
diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S index 687e5fdc9683..99b665e2b1d5 100644 --- a/arch/ia64/ia32/ia32_entry.S +++ b/arch/ia64/ia32/ia32_entry.S | |||
@@ -52,43 +52,6 @@ ENTRY(ia32_clone) | |||
52 | br.ret.sptk.many rp | 52 | br.ret.sptk.many rp |
53 | END(ia32_clone) | 53 | END(ia32_clone) |
54 | 54 | ||
55 | ENTRY(sys32_rt_sigsuspend) | ||
56 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) | ||
57 | alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs | ||
58 | mov loc0=rp | ||
59 | mov out0=in0 // mask | ||
60 | mov out1=in1 // sigsetsize | ||
61 | mov out2=sp // out2 = &sigscratch | ||
62 | .fframe 16 | ||
63 | adds sp=-16,sp // allocate dummy "sigscratch" | ||
64 | ;; | ||
65 | .body | ||
66 | br.call.sptk.many rp=ia32_rt_sigsuspend | ||
67 | 1: .restore sp | ||
68 | adds sp=16,sp | ||
69 | mov rp=loc0 | ||
70 | mov ar.pfs=loc1 | ||
71 | br.ret.sptk.many rp | ||
72 | END(sys32_rt_sigsuspend) | ||
73 | |||
74 | ENTRY(sys32_sigsuspend) | ||
75 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) | ||
76 | alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs | ||
77 | mov loc0=rp | ||
78 | mov out0=in2 // mask (first two args are ignored) | ||
79 | ;; | ||
80 | mov out1=sp // out1 = &sigscratch | ||
81 | .fframe 16 | ||
82 | adds sp=-16,sp // allocate dummy "sigscratch" | ||
83 | .body | ||
84 | br.call.sptk.many rp=ia32_sigsuspend | ||
85 | 1: .restore sp | ||
86 | adds sp=16,sp | ||
87 | mov rp=loc0 | ||
88 | mov ar.pfs=loc1 | ||
89 | br.ret.sptk.many rp | ||
90 | END(sys32_sigsuspend) | ||
91 | |||
92 | GLOBAL_ENTRY(ia32_ret_from_clone) | 55 | GLOBAL_ENTRY(ia32_ret_from_clone) |
93 | PT_REGS_UNWIND_INFO(0) | 56 | PT_REGS_UNWIND_INFO(0) |
94 | { /* | 57 | { /* |
@@ -389,7 +352,7 @@ ia32_syscall_table: | |||
389 | data8 sys_rt_sigpending | 352 | data8 sys_rt_sigpending |
390 | data8 compat_sys_rt_sigtimedwait | 353 | data8 compat_sys_rt_sigtimedwait |
391 | data8 sys32_rt_sigqueueinfo | 354 | data8 sys32_rt_sigqueueinfo |
392 | data8 sys32_rt_sigsuspend | 355 | data8 compat_sys_rt_sigsuspend |
393 | data8 sys32_pread /* 180 */ | 356 | data8 sys32_pread /* 180 */ |
394 | data8 sys32_pwrite | 357 | data8 sys32_pwrite |
395 | data8 sys_chown /* 16-bit version */ | 358 | data8 sys_chown /* 16-bit version */ |
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index 7b38b73e7827..b2bb7f227920 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c | |||
@@ -452,59 +452,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r | |||
452 | sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); | 452 | sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); |
453 | } | 453 | } |
454 | 454 | ||
455 | long | 455 | asmlinkage long |
456 | __ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) | 456 | sys32_sigsuspend (int history0, int history1, old_sigset_t mask) |
457 | { | 457 | { |
458 | extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); | 458 | mask &= _BLOCKABLE; |
459 | sigset_t oldset, set; | ||
460 | |||
461 | scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */ | ||
462 | memset(&set, 0, sizeof(set)); | ||
463 | |||
464 | memcpy(&set.sig, &sset->sig, sigsetsize); | ||
465 | |||
466 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
467 | |||
468 | spin_lock_irq(¤t->sighand->siglock); | 459 | spin_lock_irq(¤t->sighand->siglock); |
469 | { | 460 | current->saved_sigmask = current->blocked; |
470 | oldset = current->blocked; | 461 | siginitset(¤t->blocked, mask); |
471 | current->blocked = set; | 462 | recalc_sigpending(); |
472 | recalc_sigpending(); | ||
473 | } | ||
474 | spin_unlock_irq(¤t->sighand->siglock); | 463 | spin_unlock_irq(¤t->sighand->siglock); |
475 | 464 | ||
476 | /* | 465 | current->state = TASK_INTERRUPTIBLE; |
477 | * The return below usually returns to the signal handler. We need to pre-set the | 466 | schedule(); |
478 | * correct error code here to ensure that the right values get saved in sigcontext | 467 | set_thread_flag(TIF_RESTORE_SIGMASK); |
479 | * by ia64_do_signal. | 468 | return -ERESTARTNOHAND; |
480 | */ | ||
481 | scr->pt.r8 = -EINTR; | ||
482 | while (1) { | ||
483 | current->state = TASK_INTERRUPTIBLE; | ||
484 | schedule(); | ||
485 | if (ia64_do_signal(&oldset, scr, 1)) | ||
486 | return -EINTR; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | asmlinkage long | ||
491 | ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr) | ||
492 | { | ||
493 | compat_sigset_t set; | ||
494 | |||
495 | if (sigsetsize > sizeof(compat_sigset_t)) | ||
496 | return -EINVAL; | ||
497 | |||
498 | if (copy_from_user(&set.sig, &uset->sig, sigsetsize)) | ||
499 | return -EFAULT; | ||
500 | |||
501 | return __ia32_rt_sigsuspend(&set, sigsetsize, scr); | ||
502 | } | ||
503 | |||
504 | asmlinkage long | ||
505 | ia32_sigsuspend (unsigned int mask, struct sigscratch *scr) | ||
506 | { | ||
507 | return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr); | ||
508 | } | 469 | } |
509 | 470 | ||
510 | asmlinkage long | 471 | asmlinkage long |
diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index 55fd2d5471e1..156a6fa031f4 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S | |||
@@ -1199,32 +1199,6 @@ ENTRY(notify_resume_user) | |||
1199 | br.ret.sptk.many rp | 1199 | br.ret.sptk.many rp |
1200 | END(notify_resume_user) | 1200 | END(notify_resume_user) |
1201 | 1201 | ||
1202 | GLOBAL_ENTRY(sys_rt_sigsuspend) | ||
1203 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) | ||
1204 | alloc loc1=ar.pfs,8,2,3,0 // preserve all eight input regs in case of syscall restart! | ||
1205 | mov r9=ar.unat | ||
1206 | mov loc0=rp // save return address | ||
1207 | mov out0=in0 // mask | ||
1208 | mov out1=in1 // sigsetsize | ||
1209 | adds out2=8,sp // out2=&sigscratch->ar_pfs | ||
1210 | ;; | ||
1211 | .fframe 16 | ||
1212 | .spillsp ar.unat, 16 | ||
1213 | st8 [sp]=r9,-16 // allocate space for ar.unat and save it | ||
1214 | st8 [out2]=loc1,-8 // save ar.pfs, out2=&sigscratch | ||
1215 | .body | ||
1216 | br.call.sptk.many rp=ia64_rt_sigsuspend | ||
1217 | .ret17: .restore sp | ||
1218 | adds sp=16,sp // pop scratch stack space | ||
1219 | ;; | ||
1220 | ld8 r9=[sp] // load new unat from sw->caller_unat | ||
1221 | mov rp=loc0 | ||
1222 | ;; | ||
1223 | mov ar.unat=r9 | ||
1224 | mov ar.pfs=loc1 | ||
1225 | br.ret.sptk.many rp | ||
1226 | END(sys_rt_sigsuspend) | ||
1227 | |||
1228 | ENTRY(sys_rt_sigreturn) | 1202 | ENTRY(sys_rt_sigreturn) |
1229 | PT_REGS_UNWIND_INFO(0) | 1203 | PT_REGS_UNWIND_INFO(0) |
1230 | /* | 1204 | /* |
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index cba6ac398736..d7b7d3da1ebb 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c | |||
@@ -156,7 +156,7 @@ show_regs (struct pt_regs *regs) | |||
156 | } | 156 | } |
157 | 157 | ||
158 | void | 158 | void |
159 | do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | 159 | do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall) |
160 | { | 160 | { |
161 | if (fsys_mode(current, &scr->pt)) { | 161 | if (fsys_mode(current, &scr->pt)) { |
162 | /* defer signal-handling etc. until we return to privilege-level 0. */ | 162 | /* defer signal-handling etc. until we return to privilege-level 0. */ |
@@ -171,8 +171,8 @@ do_notify_resume_user (sigset_t *oldset, struct sigscratch *scr, long in_syscall | |||
171 | #endif | 171 | #endif |
172 | 172 | ||
173 | /* deal with pending signal delivery */ | 173 | /* deal with pending signal delivery */ |
174 | if (test_thread_flag(TIF_SIGPENDING)) | 174 | if (test_thread_flag(TIF_SIGPENDING)||test_thread_flag(TIF_RESTORE_SIGMASK)) |
175 | ia64_do_signal(oldset, scr, in_syscall); | 175 | ia64_do_signal(scr, in_syscall); |
176 | } | 176 | } |
177 | 177 | ||
178 | static int pal_halt = 1; | 178 | static int pal_halt = 1; |
diff --git a/arch/ia64/kernel/sigframe.h b/arch/ia64/kernel/sigframe.h index 37b986cb86e0..9fd9a1933b3d 100644 --- a/arch/ia64/kernel/sigframe.h +++ b/arch/ia64/kernel/sigframe.h | |||
@@ -22,4 +22,4 @@ struct sigframe { | |||
22 | struct sigcontext sc; | 22 | struct sigcontext sc; |
23 | }; | 23 | }; |
24 | 24 | ||
25 | extern long ia64_do_signal (sigset_t *, struct sigscratch *, long); | 25 | extern void ia64_do_signal (struct sigscratch *, long); |
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 77f8b49c7882..034b81d62bb1 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
@@ -41,47 +41,6 @@ | |||
41 | # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) | 41 | # define GET_SIGSET(k,u) __get_user((k)->sig[0], &(u)->sig[0]) |
42 | #endif | 42 | #endif |
43 | 43 | ||
44 | long | ||
45 | ia64_rt_sigsuspend (sigset_t __user *uset, size_t sigsetsize, struct sigscratch *scr) | ||
46 | { | ||
47 | sigset_t oldset, set; | ||
48 | |||
49 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
50 | if (sigsetsize != sizeof(sigset_t)) | ||
51 | return -EINVAL; | ||
52 | |||
53 | if (!access_ok(VERIFY_READ, uset, sigsetsize)) | ||
54 | return -EFAULT; | ||
55 | |||
56 | if (GET_SIGSET(&set, uset)) | ||
57 | return -EFAULT; | ||
58 | |||
59 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
60 | |||
61 | spin_lock_irq(¤t->sighand->siglock); | ||
62 | { | ||
63 | oldset = current->blocked; | ||
64 | current->blocked = set; | ||
65 | recalc_sigpending(); | ||
66 | } | ||
67 | spin_unlock_irq(¤t->sighand->siglock); | ||
68 | |||
69 | /* | ||
70 | * The return below usually returns to the signal handler. We need to | ||
71 | * pre-set the correct error code here to ensure that the right values | ||
72 | * get saved in sigcontext by ia64_do_signal. | ||
73 | */ | ||
74 | scr->pt.r8 = EINTR; | ||
75 | scr->pt.r10 = -1; | ||
76 | |||
77 | while (1) { | ||
78 | current->state = TASK_INTERRUPTIBLE; | ||
79 | schedule(); | ||
80 | if (ia64_do_signal(&oldset, scr, 1)) | ||
81 | return -EINTR; | ||
82 | } | ||
83 | } | ||
84 | |||
85 | asmlinkage long | 44 | asmlinkage long |
86 | sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, | 45 | sys_sigaltstack (const stack_t __user *uss, stack_t __user *uoss, long arg2, |
87 | long arg3, long arg4, long arg5, long arg6, long arg7, | 46 | long arg3, long arg4, long arg5, long arg6, long arg7, |
@@ -478,10 +437,11 @@ handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigse | |||
478 | * Note that `init' is a special process: it doesn't get signals it doesn't want to | 437 | * Note that `init' is a special process: it doesn't get signals it doesn't want to |
479 | * handle. Thus you cannot kill init even with a SIGKILL even by mistake. | 438 | * handle. Thus you cannot kill init even with a SIGKILL even by mistake. |
480 | */ | 439 | */ |
481 | long | 440 | void |
482 | ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | 441 | ia64_do_signal (struct sigscratch *scr, long in_syscall) |
483 | { | 442 | { |
484 | struct k_sigaction ka; | 443 | struct k_sigaction ka; |
444 | sigset_t *oldset; | ||
485 | siginfo_t info; | 445 | siginfo_t info; |
486 | long restart = in_syscall; | 446 | long restart = in_syscall; |
487 | long errno = scr->pt.r8; | 447 | long errno = scr->pt.r8; |
@@ -493,9 +453,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
493 | * doing anything if so. | 453 | * doing anything if so. |
494 | */ | 454 | */ |
495 | if (!user_mode(&scr->pt)) | 455 | if (!user_mode(&scr->pt)) |
496 | return 0; | 456 | return; |
497 | 457 | ||
498 | if (!oldset) | 458 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
459 | oldset = ¤t->saved_sigmask; | ||
460 | else | ||
499 | oldset = ¤t->blocked; | 461 | oldset = ¤t->blocked; |
500 | 462 | ||
501 | /* | 463 | /* |
@@ -558,8 +520,15 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
558 | * Whee! Actually deliver the signal. If the delivery failed, we need to | 520 | * Whee! Actually deliver the signal. If the delivery failed, we need to |
559 | * continue to iterate in this loop so we can deliver the SIGSEGV... | 521 | * continue to iterate in this loop so we can deliver the SIGSEGV... |
560 | */ | 522 | */ |
561 | if (handle_signal(signr, &ka, &info, oldset, scr)) | 523 | if (handle_signal(signr, &ka, &info, oldset, scr)) { |
562 | return 1; | 524 | /* a signal was successfully delivered; the saved |
525 | * sigmask will have been stored in the signal frame, | ||
526 | * and will be restored by sigreturn, so we can simply | ||
527 | * clear the TIF_RESTORE_SIGMASK flag */ | ||
528 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) | ||
529 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
530 | return; | ||
531 | } | ||
563 | } | 532 | } |
564 | 533 | ||
565 | /* Did we come from a system call? */ | 534 | /* Did we come from a system call? */ |
@@ -585,5 +554,11 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
585 | } | 554 | } |
586 | } | 555 | } |
587 | } | 556 | } |
588 | return 0; | 557 | |
558 | /* if there's no signal to deliver, we just put the saved sigmask | ||
559 | * back */ | ||
560 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) { | ||
561 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
562 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); | ||
563 | } | ||
589 | } | 564 | } |