summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/truss/expound.c10
-rw-r--r--usr/src/cmd/truss/systable.c4
-rw-r--r--usr/src/lib/libc/common/sys/__signotify.s19
-rw-r--r--usr/src/lib/libc/port/threads/sigaction.c45
-rw-r--r--usr/src/uts/common/os/sysent.c9
-rw-r--r--usr/src/uts/common/sys/syscall.h3
-rw-r--r--usr/src/uts/common/syscall/signotify.c65
-rw-r--r--usr/src/uts/intel/os/name_to_sysnum1
-rw-r--r--usr/src/uts/sparc/os/name_to_sysnum1
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