diff options
Diffstat (limited to 'usr/src')
-rw-r--r-- | usr/src/cmd/truss/expound.c | 10 | ||||
-rw-r--r-- | usr/src/cmd/truss/systable.c | 4 | ||||
-rw-r--r-- | usr/src/lib/libc/common/sys/__signotify.s | 19 | ||||
-rw-r--r-- | usr/src/lib/libc/port/threads/sigaction.c | 45 | ||||
-rw-r--r-- | usr/src/uts/common/os/sysent.c | 9 | ||||
-rw-r--r-- | usr/src/uts/common/sys/syscall.h | 3 | ||||
-rw-r--r-- | usr/src/uts/common/syscall/signotify.c | 65 | ||||
-rw-r--r-- | usr/src/uts/intel/os/name_to_sysnum | 1 | ||||
-rw-r--r-- | usr/src/uts/sparc/os/name_to_sysnum | 1 |
9 files changed, 112 insertions, 45 deletions
diff --git a/usr/src/cmd/truss/expound.c b/usr/src/cmd/truss/expound.c index 479f584561..22f29b9d81 100644 --- a/usr/src/cmd/truss/expound.c +++ b/usr/src/cmd/truss/expound.c @@ -4940,6 +4940,16 @@ expound(private_t *pri, long r0, int raw) show_sigaction(pri, (long)pri->sys_args[2], "old", r0); break; + case SYS_signotify: + if (pri->sys_nargs > 1) + show_siginfo(pri, (long)pri->sys_args[1]); + break; + case SYS_sigresend: + if (pri->sys_nargs > 1) + show_siginfo(pri, (long)pri->sys_args[1]); + if (pri->sys_nargs > 2) + show_sigset(pri, (long)pri->sys_args[2], "sigmask"); + break; case SYS_sigpending: if (!err && pri->sys_nargs > 1) show_sigset(pri, (long)pri->sys_args[1], "sigmask"); diff --git a/usr/src/cmd/truss/systable.c b/usr/src/cmd/truss/systable.c index b960898928..58b8065178 100644 --- a/usr/src/cmd/truss/systable.c +++ b/usr/src/cmd/truss/systable.c @@ -332,8 +332,8 @@ const struct systable systable[] = { {"waitid", 4, DEC, NOV, IDT, DEC, HEX, WOP}, /* 107 */ {"sigsendsys", 2, DEC, NOV, HEX, SIG}, /* 108 */ {"hrtsys", 5, DEC, NOV, DEC, HEX, HEX, HEX, HEX}, /* 109 */ -{"acancel", 3, DEC, NOV, DEC, HEX, DEC}, /* 110 */ -{"async", 3, DEC, NOV, DEC, HEX, DEC}, /* 111 */ +{ NULL, 8, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX, HEX}, +{"sigresend", 3, DEC, NOV, SIG, HEX, HEX}, /* 111 */ {"priocntlsys", 5, DEC, NOV, DEC, HEX, DEC, PC4, PC5}, /* 112 */ {"pathconf", 2, DEC, NOV, STG, PTC}, /* 113 */ {"mincore", 3, DEC, NOV, HEX, UNS, HEX}, /* 114 */ diff --git a/usr/src/lib/libc/common/sys/__signotify.s b/usr/src/lib/libc/common/sys/__signotify.s index 057a00ad45..c46122d074 100644 --- a/usr/src/lib/libc/common/sys/__signotify.s +++ b/usr/src/lib/libc/common/sys/__signotify.s @@ -20,7 +20,7 @@ */ /* - * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -28,11 +28,22 @@ .file "%M%" -/* unpublished system call for POSIX message queues -- __signotify */ -/* int __signotify (int cmd, siginfo_t *siginfo, signotify_id_t *sn_id); */ - #include "SYS.h" +/* + * Unpublished system call for POSIX message queues. + * int __signotify(int cmd, siginfo_t *siginfo, signotify_id_t *sn_id); + */ SYSCALL2_RVAL1(__signotify,signotify) RET SET_SIZE(__signotify) + +/* + * Unpublished system call to support deferred signals in libc. + * int __sigresend(int sig, siginfo_t *siginfo, sigset_t *mask); + */ + ENTRY(__sigresend) + SYSTRAP_RVAL1(sigresend) + SYSLWPERR + RET + SET_SIZE(__sigresend) diff --git a/usr/src/lib/libc/port/threads/sigaction.c b/usr/src/lib/libc/port/threads/sigaction.c index 3d8f747100..31cd052c00 100644 --- a/usr/src/lib/libc/port/threads/sigaction.c +++ b/usr/src/lib/libc/port/threads/sigaction.c @@ -214,45 +214,32 @@ out: * We are out of the critical region and are ready to take a signal. * The kernel has all signals blocked on this lwp, but our value of * ul_sigmask is the correct signal mask for the previous context. + * + * We call __sigresend() to atomically restore the signal mask and + * cause the signal to be sent again with the remembered siginfo. + * We will not return successfully from __sigresend() until the + * application's signal handler has been run via sigacthandler(). */ void take_deferred_signal(int sig) { + extern int __sigresend(int, siginfo_t *, sigset_t *); ulwp_t *self = curthread; - siginfo_t siginfo; siginfo_t *sip; - ucontext_t uc; - volatile int returning; + int error; - ASSERT(self->ul_critical == 0); - ASSERT(self->ul_sigdefer == 0); - ASSERT(self->ul_cursig == 0); + ASSERT((self->ul_critical | self->ul_sigdefer | self->ul_cursig) == 0); - returning = 0; - uc.uc_flags = UC_ALL; - /* - * We call _private_getcontext (a libc-private synonym for - * _getcontext) rather than _getcontext because we need to - * avoid the dynamic linker and link auditing problems here. - */ - (void) _private_getcontext(&uc); - /* - * If the application signal handler calls setcontext() on - * the ucontext we give it, it returns here, then we return. - */ - if (returning) - return; - returning = 1; - ASSERT(sigequalset(&uc.uc_sigmask, &maskset)); if (self->ul_siginfo.si_signo == 0) sip = NULL; - else { - (void) _private_memcpy(&siginfo, - &self->ul_siginfo, sizeof (siginfo)); - sip = &siginfo; - } - uc.uc_sigmask = self->ul_sigmask; - call_user_handler(sig, sip, &uc); + else + sip = &self->ul_siginfo; + + /* EAGAIN can happen only for a pending SIGSTOP signal */ + while ((error = __sigresend(sig, sip, &self->ul_sigmask)) == EAGAIN) + continue; + if (error) + thr_panic("take_deferred_signal(): __sigresend() failed"); } void diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c index a878cee623..38c3270f9b 100644 --- a/usr/src/uts/common/os/sysent.c +++ b/usr/src/uts/common/os/sysent.c @@ -116,6 +116,7 @@ int sigsuspend(); int sigaltstack(); int sigaction(); int sigpending(); +int sigresend(); int sigtimedwait(); int getsetcontext(); int stat(); @@ -565,8 +566,8 @@ struct sysent sysent[NSYSCALL] = /* 109 */ IF_x86( SYSENT_AP("hrtsys", hrtsys, 5), SYSENT_LOADABLE()), - /* 110 */ SYSENT_LOADABLE(), /* was acancel */ - /* 111 */ SYSENT_LOADABLE(), /* was async */ + /* 110 */ SYSENT_LOADABLE(), + /* 111 */ SYSENT_CI("sigresend", sigresend, 3), /* 112 */ SYSENT_CL("priocntlsys", priocntlsys, 5), /* 113 */ SYSENT_CL("pathconf", pathconf, 2), /* 114 */ SYSENT_CI("mincore", mincore, 3), @@ -962,8 +963,8 @@ struct sysent sysent32[NSYSCALL] = /* 109 */ IF_x86( SYSENT_AP("hrtsys", hrtsys, 5), SYSENT_LOADABLE32()), - /* 110 */ SYSENT_LOADABLE32(), /* was acancel */ - /* 111 */ SYSENT_LOADABLE32(), /* was async */ + /* 110 */ SYSENT_LOADABLE32(), + /* 111 */ SYSENT_CI("sigresend", sigresend, 3), /* 112 */ SYSENT_CI("priocntlsys", priocntlsys, 5), /* 113 */ SYSENT_CI("pathconf", pathconf, 2), /* 114 */ SYSENT_CI("mincore", mincore, 3), diff --git a/usr/src/uts/common/sys/syscall.h b/usr/src/uts/common/sys/syscall.h index ae7e8224da..9fbc05f054 100644 --- a/usr/src/uts/common/sys/syscall.h +++ b/usr/src/uts/common/sys/syscall.h @@ -299,8 +299,7 @@ extern "C" { #define SYS_waitsys 107 #define SYS_sigsendsys 108 #define SYS_hrtsys 109 -#define SYS_acancel 110 -#define SYS_async 111 +#define SYS_sigresend 111 #define SYS_priocntlsys 112 #define SYS_pathconf 113 #define SYS_mincore 114 diff --git a/usr/src/uts/common/syscall/signotify.c b/usr/src/uts/common/syscall/signotify.c index 0c32a0cd5e..860e22bd24 100644 --- a/usr/src/uts/common/syscall/signotify.c +++ b/usr/src/uts/common/syscall/signotify.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -19,8 +18,9 @@ * * CDDL HEADER END */ + /* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,6 +36,7 @@ #include <sys/fault.h> #include <sys/signal.h> #include <sys/siginfo.h> +#include <sys/schedctl.h> #include <vm/as.h> #include <sys/debug.h> #include <sys/contract/process_impl.h> @@ -224,3 +225,59 @@ signotify(int cmd, siginfo_t *siginfo, signotify_id_t *sn_id) return (0); } + +int +sigresend(int sig, siginfo_t *siginfo, sigset_t *mask) +{ + kthread_t *t = curthread; + proc_t *p = ttoproc(t); + klwp_t *lwp = ttolwp(t); + sigqueue_t *sqp = kmem_zalloc(sizeof (*sqp), KM_SLEEP); + sigset_t set; + k_sigset_t kset; + int error; + + if (sig <= 0 || sig >= NSIG || sigismember(&cantmask, sig)) { + error = EINVAL; + goto bad; + } + + if (siginfo == NULL) { + sqp->sq_info.si_signo = sig; + sqp->sq_info.si_code = SI_NOINFO; + } else { + if (copyin_siginfo(get_udatamodel(), siginfo, &sqp->sq_info)) { + error = EFAULT; + goto bad; + } + if (sqp->sq_info.si_signo != sig) { + error = EINVAL; + goto bad; + } + } + + if (copyin(mask, &set, sizeof (set))) { + error = EFAULT; + goto bad; + } + sigutok(&set, &kset); + + mutex_enter(&p->p_lock); + if (lwp->lwp_cursig || lwp->lwp_curinfo) { + mutex_exit(&p->p_lock); + t->t_sig_check = 1; + error = EAGAIN; + goto bad; + } + lwp->lwp_cursig = sig; + lwp->lwp_curinfo = sqp; + schedctl_finish_sigblock(t); + t->t_hold = kset; + mutex_exit(&p->p_lock); + + t->t_sig_check = 1; + return (0); +bad: + kmem_free(sqp, sizeof (*sqp)); + return (set_errno(error)); +} diff --git a/usr/src/uts/intel/os/name_to_sysnum b/usr/src/uts/intel/os/name_to_sysnum index 3dec822452..5e744378fd 100644 --- a/usr/src/uts/intel/os/name_to_sysnum +++ b/usr/src/uts/intel/os/name_to_sysnum @@ -97,6 +97,7 @@ getloadavg 105 nfs 106 waitsys 107 sigsendsys 108 +sigresend 111 priocntlsys 112 pathconf 113 mincore 114 diff --git a/usr/src/uts/sparc/os/name_to_sysnum b/usr/src/uts/sparc/os/name_to_sysnum index e78b26e72f..b4b4af1b9b 100644 --- a/usr/src/uts/sparc/os/name_to_sysnum +++ b/usr/src/uts/sparc/os/name_to_sysnum @@ -96,6 +96,7 @@ getloadavg 105 nfs 106 waitsys 107 sigsendsys 108 +sigresend 111 priocntlsys 112 pathconf 113 mincore 114 |