10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate
300Sstevel@tonic-gate /*
310Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD
320Sstevel@tonic-gate * under license from the Regents of the University of California.
330Sstevel@tonic-gate */
340Sstevel@tonic-gate
350Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
360Sstevel@tonic-gate
370Sstevel@tonic-gate /*LINTLIBRARY*/
380Sstevel@tonic-gate
390Sstevel@tonic-gate /*
400Sstevel@tonic-gate * 4.3BSD signal compatibility functions
410Sstevel@tonic-gate *
420Sstevel@tonic-gate * the implementation interprets signal masks equal to -1 as "all of the
430Sstevel@tonic-gate * signals in the signal set", thereby allowing signals with numbers
440Sstevel@tonic-gate * above 32 to be blocked when referenced in code such as:
450Sstevel@tonic-gate *
460Sstevel@tonic-gate * for (i = 0; i < NSIG; i++)
470Sstevel@tonic-gate * mask |= sigmask(i)
480Sstevel@tonic-gate */
490Sstevel@tonic-gate
500Sstevel@tonic-gate #include <sys/types.h>
510Sstevel@tonic-gate #include <ucontext.h>
520Sstevel@tonic-gate #include <signal.h>
530Sstevel@tonic-gate #include <errno.h>
540Sstevel@tonic-gate
550Sstevel@tonic-gate #undef BUS_OBJERR /* namespace conflict */
560Sstevel@tonic-gate #include <sys/siginfo.h>
570Sstevel@tonic-gate #include "libc.h"
580Sstevel@tonic-gate
590Sstevel@tonic-gate #pragma weak sigvechandler = _sigvechandler
600Sstevel@tonic-gate #pragma weak sigsetmask = _sigsetmask
610Sstevel@tonic-gate #pragma weak sigblock = _sigblock
620Sstevel@tonic-gate #pragma weak sigpause = usigpause
630Sstevel@tonic-gate #pragma weak sigvec = _sigvec
640Sstevel@tonic-gate #pragma weak sigstack = _sigstack
650Sstevel@tonic-gate #pragma weak signal = usignal
660Sstevel@tonic-gate #pragma weak siginterrupt = _siginterrupt
670Sstevel@tonic-gate
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate * DO NOT remove the _ from these 3 functions or the subsequent
700Sstevel@tonic-gate * calls to them below. The non _ versions of these functions
710Sstevel@tonic-gate * are the wrong functions to call. This is BCP. Extra
720Sstevel@tonic-gate * care should be taken when modifying this code.
730Sstevel@tonic-gate */
740Sstevel@tonic-gate extern int _sigfillset(sigset_t *);
750Sstevel@tonic-gate extern int _sigemptyset(sigset_t *);
760Sstevel@tonic-gate extern int _sigprocmask(int, const sigset_t *, sigset_t *);
770Sstevel@tonic-gate
780Sstevel@tonic-gate #define set2mask(setp) ((setp)->__sigbits[0])
790Sstevel@tonic-gate #define mask2set(mask, setp) \
800Sstevel@tonic-gate ((mask) == -1 ? _sigfillset(setp) : \
810Sstevel@tonic-gate ((void) _sigemptyset(setp), (((setp)->__sigbits[0]) = (int)(mask))))
820Sstevel@tonic-gate
830Sstevel@tonic-gate void (*_siguhandler[NSIG])() = { 0 };
840Sstevel@tonic-gate
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate * forward declarations
870Sstevel@tonic-gate */
880Sstevel@tonic-gate int ucbsiginterrupt(int, int);
890Sstevel@tonic-gate int ucbsigvec(int, struct sigvec *, struct sigvec *);
900Sstevel@tonic-gate int ucbsigpause(int);
910Sstevel@tonic-gate int ucbsigblock(int);
920Sstevel@tonic-gate int ucbsigsetmask(int);
930Sstevel@tonic-gate static void ucbsigvechandler(int, siginfo_t *, ucontext_t *);
940Sstevel@tonic-gate
950Sstevel@tonic-gate /*
960Sstevel@tonic-gate * sigvechandler is the real signal handler installed for all
970Sstevel@tonic-gate * signals handled in the 4.3BSD compatibility interface - it translates
980Sstevel@tonic-gate * SVR4 signal hander arguments into 4.3BSD signal handler arguments
990Sstevel@tonic-gate * and then calls the real handler
1000Sstevel@tonic-gate */
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate int
_sigvechandler(int sig,siginfo_t * sip,ucontext_t * ucp)1030Sstevel@tonic-gate _sigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp)
1040Sstevel@tonic-gate {
1050Sstevel@tonic-gate ucbsigvechandler(sig, sip, ucp);
1060Sstevel@tonic-gate return (0); /* keep the same as the original prototype */
1070Sstevel@tonic-gate }
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate static void
ucbsigvechandler(int sig,siginfo_t * sip,ucontext_t * ucp)1100Sstevel@tonic-gate ucbsigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp)
1110Sstevel@tonic-gate {
1120Sstevel@tonic-gate struct sigcontext sc;
1130Sstevel@tonic-gate int code;
1140Sstevel@tonic-gate char *addr;
1150Sstevel@tonic-gate #ifdef NEVER
1160Sstevel@tonic-gate int gwinswitch = 0;
1170Sstevel@tonic-gate #endif
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0);
1200Sstevel@tonic-gate sc.sc_mask = set2mask(&ucp->uc_sigmask);
1210Sstevel@tonic-gate
1220Sstevel@tonic-gate #if defined(__sparc)
1230Sstevel@tonic-gate if (sig == SIGFPE && sip != NULL && SI_FROMKERNEL(sip) &&
1240Sstevel@tonic-gate (sip->si_code == FPE_INTDIV || sip->si_code == FPE_INTOVF)) {
1250Sstevel@tonic-gate /*
1260Sstevel@tonic-gate * Hack to emulate the 4.x kernel behavior of incrementing
1270Sstevel@tonic-gate * the PC on integer divide by zero and integer overflow
1280Sstevel@tonic-gate * on sparc machines. (5.x does not increment the PC.)
1290Sstevel@tonic-gate */
1300Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PC] =
131*712Smuffin ucp->uc_mcontext.gregs[REG_nPC];
1320Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_nPC] += 4;
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate sc.sc_sp = ucp->uc_mcontext.gregs[REG_SP];
1350Sstevel@tonic-gate sc.sc_pc = ucp->uc_mcontext.gregs[REG_PC];
1360Sstevel@tonic-gate sc.sc_npc = ucp->uc_mcontext.gregs[REG_nPC];
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate /* XX64 There is no REG_PSR for sparcv9, we map in REG_CCR for now */
1390Sstevel@tonic-gate #if defined(__sparcv9)
1400Sstevel@tonic-gate sc.sc_psr = ucp->uc_mcontext.gregs[REG_CCR];
1410Sstevel@tonic-gate #else
1420Sstevel@tonic-gate sc.sc_psr = ucp->uc_mcontext.gregs[REG_PSR];
1430Sstevel@tonic-gate #endif
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate sc.sc_g1 = ucp->uc_mcontext.gregs[REG_G1];
1460Sstevel@tonic-gate sc.sc_o0 = ucp->uc_mcontext.gregs[REG_O0];
1470Sstevel@tonic-gate
1480Sstevel@tonic-gate /*
1490Sstevel@tonic-gate * XXX - What a kludge!
1500Sstevel@tonic-gate * Store a pointer to the original ucontext_t in the sigcontext
1510Sstevel@tonic-gate * so that it's available to the sigcleanup call that needs to
1520Sstevel@tonic-gate * return from the signal handler. Otherwise, vital information
1530Sstevel@tonic-gate * (e.g., the "out" registers) that's only saved in the
1540Sstevel@tonic-gate * ucontext_t isn't available to sigcleanup.
1550Sstevel@tonic-gate */
1560Sstevel@tonic-gate sc.sc_wbcnt = (int)(sizeof (*ucp));
157*712Smuffin sc.sc_spbuf[0] = (char *)(uintptr_t)sig;
1580Sstevel@tonic-gate sc.sc_spbuf[1] = (char *)ucp;
1590Sstevel@tonic-gate #ifdef NEVER
1600Sstevel@tonic-gate /*
1610Sstevel@tonic-gate * XXX - Sorry, we can never pass the saved register windows
1620Sstevel@tonic-gate * on in the sigcontext because we use that space to save the
1630Sstevel@tonic-gate * ucontext_t.
1640Sstevel@tonic-gate */
1650Sstevel@tonic-gate if (ucp->uc_mcontext.gwins != (gwindows_t *)0) {
1660Sstevel@tonic-gate int i, j;
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate gwinswitch = 1;
1690Sstevel@tonic-gate sc.sc_wbcnt = ucp->uc_mcontext.gwins->wbcnt;
1700Sstevel@tonic-gate /* XXX - should use bcopy to move this in bulk */
1710Sstevel@tonic-gate for (i = 0; i < ucp->uc_mcontext.gwins; i++) {
1720Sstevel@tonic-gate sc.sc_spbuf[i] = ucp->uc_mcontext.gwins->spbuf[i];
1730Sstevel@tonic-gate for (j = 0; j < 8; j++)
1740Sstevel@tonic-gate sc.sc_wbuf[i][j] =
1750Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbuf[i].rw_local[j];
1760Sstevel@tonic-gate for (j = 0; j < 8; j++)
1770Sstevel@tonic-gate sc.sc_wbuf[i][j+8] =
1780Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbuf[i].rw_in[j];
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate }
1810Sstevel@tonic-gate #endif
1820Sstevel@tonic-gate #endif
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate * Translate signal codes from new to old.
1860Sstevel@tonic-gate * /usr/include/sys/siginfo.h contains new codes.
1870Sstevel@tonic-gate * /usr/ucbinclude/sys/signal.h contains old codes.
1880Sstevel@tonic-gate */
1890Sstevel@tonic-gate code = 0;
1900Sstevel@tonic-gate addr = SIG_NOADDR;
1910Sstevel@tonic-gate if (sip != NULL && SI_FROMKERNEL(sip)) {
1920Sstevel@tonic-gate addr = sip->si_addr;
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate switch (sig) {
1950Sstevel@tonic-gate case SIGILL:
1960Sstevel@tonic-gate switch (sip->si_code) {
1970Sstevel@tonic-gate case ILL_PRVOPC:
1980Sstevel@tonic-gate code = ILL_PRIVINSTR_FAULT;
1990Sstevel@tonic-gate break;
2000Sstevel@tonic-gate case ILL_BADSTK:
2010Sstevel@tonic-gate code = ILL_STACK;
2020Sstevel@tonic-gate break;
2030Sstevel@tonic-gate case ILL_ILLTRP:
2040Sstevel@tonic-gate code = ILL_TRAP_FAULT(sip->si_trapno);
2050Sstevel@tonic-gate break;
2060Sstevel@tonic-gate default:
2070Sstevel@tonic-gate code = ILL_ILLINSTR_FAULT;
2080Sstevel@tonic-gate break;
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate break;
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate case SIGEMT:
2130Sstevel@tonic-gate code = EMT_TAG;
2140Sstevel@tonic-gate break;
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate case SIGFPE:
2170Sstevel@tonic-gate switch (sip->si_code) {
2180Sstevel@tonic-gate case FPE_INTDIV:
2190Sstevel@tonic-gate code = FPE_INTDIV_TRAP;
2200Sstevel@tonic-gate break;
2210Sstevel@tonic-gate case FPE_INTOVF:
2220Sstevel@tonic-gate code = FPE_INTOVF_TRAP;
2230Sstevel@tonic-gate break;
2240Sstevel@tonic-gate case FPE_FLTDIV:
2250Sstevel@tonic-gate code = FPE_FLTDIV_TRAP;
2260Sstevel@tonic-gate break;
2270Sstevel@tonic-gate case FPE_FLTOVF:
2280Sstevel@tonic-gate code = FPE_FLTOVF_TRAP;
2290Sstevel@tonic-gate break;
2300Sstevel@tonic-gate case FPE_FLTUND:
2310Sstevel@tonic-gate code = FPE_FLTUND_TRAP;
2320Sstevel@tonic-gate break;
2330Sstevel@tonic-gate case FPE_FLTRES:
2340Sstevel@tonic-gate code = FPE_FLTINEX_TRAP;
2350Sstevel@tonic-gate break;
2360Sstevel@tonic-gate default:
2370Sstevel@tonic-gate code = FPE_FLTOPERR_TRAP;
2380Sstevel@tonic-gate break;
2390Sstevel@tonic-gate }
2400Sstevel@tonic-gate break;
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate case SIGBUS:
2430Sstevel@tonic-gate switch (sip->si_code) {
2440Sstevel@tonic-gate case BUS_ADRALN:
2450Sstevel@tonic-gate code = BUS_ALIGN;
2460Sstevel@tonic-gate break;
2470Sstevel@tonic-gate case BUS_ADRERR:
2480Sstevel@tonic-gate code = BUS_HWERR;
2490Sstevel@tonic-gate break;
2500Sstevel@tonic-gate default: /* BUS_OBJERR */
2510Sstevel@tonic-gate code = FC_MAKE_ERR(sip->si_errno);
2520Sstevel@tonic-gate break;
2530Sstevel@tonic-gate }
2540Sstevel@tonic-gate break;
2550Sstevel@tonic-gate
2560Sstevel@tonic-gate case SIGSEGV:
2570Sstevel@tonic-gate switch (sip->si_code) {
2580Sstevel@tonic-gate case SEGV_MAPERR:
2590Sstevel@tonic-gate code = SEGV_NOMAP;
2600Sstevel@tonic-gate break;
2610Sstevel@tonic-gate case SEGV_ACCERR:
2620Sstevel@tonic-gate code = SEGV_PROT;
2630Sstevel@tonic-gate break;
2640Sstevel@tonic-gate default:
2650Sstevel@tonic-gate code = FC_MAKE_ERR(sip->si_errno);
2660Sstevel@tonic-gate break;
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate break;
2690Sstevel@tonic-gate
2700Sstevel@tonic-gate default:
2710Sstevel@tonic-gate addr = SIG_NOADDR;
2720Sstevel@tonic-gate break;
2730Sstevel@tonic-gate }
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate (*_siguhandler[sig])(sig, code, &sc, addr);
2770Sstevel@tonic-gate
2780Sstevel@tonic-gate if (sc.sc_onstack)
2790Sstevel@tonic-gate ucp->uc_stack.ss_flags |= SS_ONSTACK;
2800Sstevel@tonic-gate else
2810Sstevel@tonic-gate ucp->uc_stack.ss_flags &= ~SS_ONSTACK;
2820Sstevel@tonic-gate mask2set(sc.sc_mask, &ucp->uc_sigmask);
2830Sstevel@tonic-gate
2840Sstevel@tonic-gate #if defined(__sparc)
2850Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_SP] = sc.sc_sp;
2860Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PC] = sc.sc_pc;
2870Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_nPC] = sc.sc_npc;
2880Sstevel@tonic-gate #if defined(__sparcv9)
2890Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_CCR] = sc.sc_psr;
2900Sstevel@tonic-gate #else
2910Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PSR] = sc.sc_psr;
2920Sstevel@tonic-gate #endif
2930Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_G1] = sc.sc_g1;
2940Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_O0] = sc.sc_o0;
2950Sstevel@tonic-gate #ifdef NEVER
2960Sstevel@tonic-gate if (gwinswitch == 1) {
2970Sstevel@tonic-gate int i, j;
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbcnt = sc.sc_wbcnt;
3000Sstevel@tonic-gate /* XXX - should use bcopy to move this in bulk */
3010Sstevel@tonic-gate for (i = 0; i < sc.sc_wbcnt; i++) {
3020Sstevel@tonic-gate ucp->uc_mcontext.gwins->spbuf[i] = sc.sc_spbuf[i];
3030Sstevel@tonic-gate for (j = 0; j < 8; j++)
3040Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbuf[i].rw_local[j] =
3050Sstevel@tonic-gate sc.sc_wbuf[i][j];
3060Sstevel@tonic-gate for (j = 0; j < 8; j++)
3070Sstevel@tonic-gate ucp->uc_mcontext.gwins->wbuf[i].rw_in[j] =
3080Sstevel@tonic-gate sc.sc_wbuf[i][j+8];
3090Sstevel@tonic-gate }
3100Sstevel@tonic-gate }
3110Sstevel@tonic-gate #endif
3120Sstevel@tonic-gate
3130Sstevel@tonic-gate if (sig == SIGFPE) {
3140Sstevel@tonic-gate if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) {
3150Sstevel@tonic-gate ucp->uc_mcontext.fpregs.fpu_qcnt--;
3160Sstevel@tonic-gate ucp->uc_mcontext.fpregs.fpu_q++;
3170Sstevel@tonic-gate }
3180Sstevel@tonic-gate }
3190Sstevel@tonic-gate #endif
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate (void) setcontext(ucp);
3220Sstevel@tonic-gate }
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate #if defined(__sparc)
3250Sstevel@tonic-gate /*
3260Sstevel@tonic-gate * Emulate the special sigcleanup trap.
3270Sstevel@tonic-gate * This is only used by statically linked 4.x applications
3280Sstevel@tonic-gate * and thus is only called by the static BCP support.
3290Sstevel@tonic-gate * It lives here because of its close relationship with
3300Sstevel@tonic-gate * the ucbsigvechandler code above.
3310Sstevel@tonic-gate *
3320Sstevel@tonic-gate * It's used by 4.x applications to:
3330Sstevel@tonic-gate * 1. return from a signal handler (in __sigtramp)
3340Sstevel@tonic-gate * 2. [sig]longjmp
3350Sstevel@tonic-gate * 3. context switch, in the old 4.x liblwp
3360Sstevel@tonic-gate */
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate void
__sigcleanup(struct sigcontext * scp)3390Sstevel@tonic-gate __sigcleanup(struct sigcontext *scp)
3400Sstevel@tonic-gate {
3410Sstevel@tonic-gate ucontext_t uc, *ucp;
3420Sstevel@tonic-gate int sig;
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate * If there's a pointer to a ucontext_t hiding in the sigcontext,
3460Sstevel@tonic-gate * we *must* use that to return, since it contains important data
3470Sstevel@tonic-gate * such as the original "out" registers when the signal occurred.
3480Sstevel@tonic-gate */
3490Sstevel@tonic-gate if (scp->sc_wbcnt == sizeof (*ucp)) {
350*712Smuffin sig = (int)(uintptr_t)scp->sc_spbuf[0];
3510Sstevel@tonic-gate ucp = (ucontext_t *)scp->sc_spbuf[1];
3520Sstevel@tonic-gate } else {
3530Sstevel@tonic-gate /*
3540Sstevel@tonic-gate * Otherwise, use a local ucontext_t and
3550Sstevel@tonic-gate * initialize it with getcontext.
3560Sstevel@tonic-gate */
3570Sstevel@tonic-gate sig = 0;
3580Sstevel@tonic-gate ucp = &uc;
3590Sstevel@tonic-gate (void) getcontext(ucp);
3600Sstevel@tonic-gate }
3610Sstevel@tonic-gate
3620Sstevel@tonic-gate if (scp->sc_onstack) {
3630Sstevel@tonic-gate ucp->uc_stack.ss_flags |= SS_ONSTACK;
3640Sstevel@tonic-gate } else
3650Sstevel@tonic-gate ucp->uc_stack.ss_flags &= ~SS_ONSTACK;
3660Sstevel@tonic-gate mask2set(scp->sc_mask, &ucp->uc_sigmask);
3670Sstevel@tonic-gate
3680Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_SP] = scp->sc_sp;
3690Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PC] = scp->sc_pc;
3700Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_nPC] = scp->sc_npc;
3710Sstevel@tonic-gate #if defined(__sparcv9)
3720Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_CCR] = scp->sc_psr;
3730Sstevel@tonic-gate #else
3740Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_PSR] = scp->sc_psr;
3750Sstevel@tonic-gate #endif
3760Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_G1] = scp->sc_g1;
3770Sstevel@tonic-gate ucp->uc_mcontext.gregs[REG_O0] = scp->sc_o0;
3780Sstevel@tonic-gate
3790Sstevel@tonic-gate if (sig == SIGFPE) {
3800Sstevel@tonic-gate if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) {
3810Sstevel@tonic-gate ucp->uc_mcontext.fpregs.fpu_qcnt--;
3820Sstevel@tonic-gate ucp->uc_mcontext.fpregs.fpu_q++;
3830Sstevel@tonic-gate }
3840Sstevel@tonic-gate }
3850Sstevel@tonic-gate (void) setcontext(ucp);
3860Sstevel@tonic-gate /* NOTREACHED */
3870Sstevel@tonic-gate }
3880Sstevel@tonic-gate #endif
3890Sstevel@tonic-gate
3900Sstevel@tonic-gate int
_sigsetmask(int mask)3910Sstevel@tonic-gate _sigsetmask(int mask)
3920Sstevel@tonic-gate {
3930Sstevel@tonic-gate return (ucbsigsetmask(mask));
3940Sstevel@tonic-gate }
3950Sstevel@tonic-gate
3960Sstevel@tonic-gate int
ucbsigsetmask(int mask)3970Sstevel@tonic-gate ucbsigsetmask(int mask)
3980Sstevel@tonic-gate {
3990Sstevel@tonic-gate sigset_t oset;
4000Sstevel@tonic-gate sigset_t nset;
4010Sstevel@tonic-gate
4020Sstevel@tonic-gate (void) _sigprocmask(0, (sigset_t *)0, &nset);
4030Sstevel@tonic-gate mask2set(mask, &nset);
4040Sstevel@tonic-gate (void) _sigprocmask(SIG_SETMASK, &nset, &oset);
4050Sstevel@tonic-gate return (set2mask(&oset));
4060Sstevel@tonic-gate }
4070Sstevel@tonic-gate
4080Sstevel@tonic-gate int
_sigblock(int mask)4090Sstevel@tonic-gate _sigblock(int mask)
4100Sstevel@tonic-gate {
4110Sstevel@tonic-gate return (ucbsigblock(mask));
4120Sstevel@tonic-gate }
4130Sstevel@tonic-gate
4140Sstevel@tonic-gate int
ucbsigblock(int mask)4150Sstevel@tonic-gate ucbsigblock(int mask)
4160Sstevel@tonic-gate {
4170Sstevel@tonic-gate sigset_t oset;
4180Sstevel@tonic-gate sigset_t nset;
4190Sstevel@tonic-gate
4200Sstevel@tonic-gate (void) _sigprocmask(0, (sigset_t *)0, &nset);
4210Sstevel@tonic-gate mask2set(mask, &nset);
4220Sstevel@tonic-gate (void) _sigprocmask(SIG_BLOCK, &nset, &oset);
4230Sstevel@tonic-gate return (set2mask(&oset));
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate int
usigpause(int mask)4270Sstevel@tonic-gate usigpause(int mask)
4280Sstevel@tonic-gate {
4290Sstevel@tonic-gate return (ucbsigpause(mask));
4300Sstevel@tonic-gate }
4310Sstevel@tonic-gate
4320Sstevel@tonic-gate int
ucbsigpause(int mask)4330Sstevel@tonic-gate ucbsigpause(int mask)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate sigset_t set, oset;
4360Sstevel@tonic-gate int ret;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate (void) _sigprocmask(0, (sigset_t *)0, &set);
4390Sstevel@tonic-gate oset = set;
4400Sstevel@tonic-gate mask2set(mask, &set);
4410Sstevel@tonic-gate ret = sigsuspend(&set);
4420Sstevel@tonic-gate (void) _sigprocmask(SIG_SETMASK, &oset, (sigset_t *)0);
4430Sstevel@tonic-gate return (ret);
4440Sstevel@tonic-gate }
4450Sstevel@tonic-gate
4460Sstevel@tonic-gate int
_sigvec(int sig,struct sigvec * nvec,struct sigvec * ovec)4470Sstevel@tonic-gate _sigvec(int sig, struct sigvec *nvec, struct sigvec *ovec)
4480Sstevel@tonic-gate {
4490Sstevel@tonic-gate return (ucbsigvec(sig, nvec, ovec));
4500Sstevel@tonic-gate }
4510Sstevel@tonic-gate
4520Sstevel@tonic-gate int
ucbsigvec(int sig,struct sigvec * nvec,struct sigvec * ovec)4530Sstevel@tonic-gate ucbsigvec(int sig, struct sigvec *nvec, struct sigvec *ovec)
4540Sstevel@tonic-gate {
4550Sstevel@tonic-gate struct sigaction nact;
4560Sstevel@tonic-gate struct sigaction oact;
4570Sstevel@tonic-gate struct sigaction *nactp;
4580Sstevel@tonic-gate void (*ohandler)(int, int, struct sigcontext *, char *);
4590Sstevel@tonic-gate void (*nhandler)(int, int, struct sigcontext *, char *);
4600Sstevel@tonic-gate
4610Sstevel@tonic-gate if (sig <= 0 || sig >= NSIG) {
4620Sstevel@tonic-gate errno = EINVAL;
4630Sstevel@tonic-gate return (-1);
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate
4660Sstevel@tonic-gate if ((long)ovec == -1L || (long)nvec == -1L) {
4670Sstevel@tonic-gate errno = EFAULT;
4680Sstevel@tonic-gate return (-1);
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate
4710Sstevel@tonic-gate ohandler = _siguhandler[sig];
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate if (nvec) {
4740Sstevel@tonic-gate (void) _sigaction(sig, (struct sigaction *)0, &nact);
4750Sstevel@tonic-gate nhandler = nvec->sv_handler;
4760Sstevel@tonic-gate /*
4770Sstevel@tonic-gate * To be compatible with the behavior of SunOS 4.x:
4780Sstevel@tonic-gate * If the new signal handler is SIG_IGN or SIG_DFL,
4790Sstevel@tonic-gate * do not change the signal's entry in the handler array.
4800Sstevel@tonic-gate * This allows a child of vfork(2) to set signal handlers
4810Sstevel@tonic-gate * to SIG_IGN or SIG_DFL without affecting the parent.
4820Sstevel@tonic-gate */
4830Sstevel@tonic-gate if ((void (*)(int))nhandler != SIG_DFL &&
4840Sstevel@tonic-gate (void (*)(int))nhandler != SIG_IGN) {
4850Sstevel@tonic-gate _siguhandler[sig] = nhandler;
4860Sstevel@tonic-gate nact.sa_handler = (void (*)(int))ucbsigvechandler;
4870Sstevel@tonic-gate } else {
4880Sstevel@tonic-gate nact.sa_handler = (void (*)(int))nhandler;
4890Sstevel@tonic-gate }
4900Sstevel@tonic-gate mask2set(nvec->sv_mask, &nact.sa_mask);
4910Sstevel@tonic-gate if (sig == SIGKILL || sig == SIGSTOP)
4920Sstevel@tonic-gate nact.sa_handler = SIG_DFL;
4930Sstevel@tonic-gate nact.sa_flags = SA_SIGINFO;
4940Sstevel@tonic-gate if (!(nvec->sv_flags & SV_INTERRUPT))
4950Sstevel@tonic-gate nact.sa_flags |= SA_RESTART;
4960Sstevel@tonic-gate if (nvec->sv_flags & SV_RESETHAND)
4970Sstevel@tonic-gate nact.sa_flags |= SA_RESETHAND;
4980Sstevel@tonic-gate if (nvec->sv_flags & SV_ONSTACK)
4990Sstevel@tonic-gate nact.sa_flags |= SA_ONSTACK;
5000Sstevel@tonic-gate nactp = &nact;
5010Sstevel@tonic-gate } else
5020Sstevel@tonic-gate nactp = (struct sigaction *)0;
5030Sstevel@tonic-gate
5040Sstevel@tonic-gate if (_sigaction(sig, nactp, &oact) < 0) {
5050Sstevel@tonic-gate _siguhandler[sig] = ohandler;
5060Sstevel@tonic-gate return (-1);
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
5090Sstevel@tonic-gate if (ovec) {
5100Sstevel@tonic-gate if (oact.sa_handler == SIG_DFL || oact.sa_handler == SIG_IGN)
5110Sstevel@tonic-gate ovec->sv_handler =
5120Sstevel@tonic-gate (void (*) (int, int, struct sigcontext *, char *))
513*712Smuffin oact.sa_handler;
5140Sstevel@tonic-gate else
5150Sstevel@tonic-gate ovec->sv_handler = ohandler;
5160Sstevel@tonic-gate ovec->sv_mask = set2mask(&oact.sa_mask);
5170Sstevel@tonic-gate ovec->sv_flags = 0;
5180Sstevel@tonic-gate if (oact.sa_flags & SA_ONSTACK)
5190Sstevel@tonic-gate ovec->sv_flags |= SV_ONSTACK;
5200Sstevel@tonic-gate if (oact.sa_flags & SA_RESETHAND)
5210Sstevel@tonic-gate ovec->sv_flags |= SV_RESETHAND;
5220Sstevel@tonic-gate if (!(oact.sa_flags & SA_RESTART))
5230Sstevel@tonic-gate ovec->sv_flags |= SV_INTERRUPT;
5240Sstevel@tonic-gate }
5250Sstevel@tonic-gate
5260Sstevel@tonic-gate return (0);
5270Sstevel@tonic-gate }
5280Sstevel@tonic-gate
5290Sstevel@tonic-gate int
_sigstack(struct sigstack * nss,struct sigstack * oss)5300Sstevel@tonic-gate _sigstack(struct sigstack *nss, struct sigstack *oss)
5310Sstevel@tonic-gate {
5320Sstevel@tonic-gate struct sigaltstack nalt;
5330Sstevel@tonic-gate struct sigaltstack oalt;
5340Sstevel@tonic-gate struct sigaltstack *naltp;
5350Sstevel@tonic-gate
5360Sstevel@tonic-gate if (nss) {
5370Sstevel@tonic-gate /*
5380Sstevel@tonic-gate * XXX: assumes stack growth is down (like sparc)
5390Sstevel@tonic-gate */
5400Sstevel@tonic-gate nalt.ss_sp = nss->ss_sp - SIGSTKSZ;
5410Sstevel@tonic-gate nalt.ss_size = SIGSTKSZ;
5420Sstevel@tonic-gate nalt.ss_flags = 0;
5430Sstevel@tonic-gate naltp = &nalt;
5440Sstevel@tonic-gate } else
5450Sstevel@tonic-gate naltp = (struct sigaltstack *)0;
5460Sstevel@tonic-gate
5470Sstevel@tonic-gate if (sigaltstack(naltp, &oalt) < 0)
5480Sstevel@tonic-gate return (-1);
5490Sstevel@tonic-gate
5500Sstevel@tonic-gate if (oss) {
5510Sstevel@tonic-gate /*
5520Sstevel@tonic-gate * XXX: assumes stack growth is down (like sparc)
5530Sstevel@tonic-gate */
5540Sstevel@tonic-gate oss->ss_sp = oalt.ss_sp + oalt.ss_size;
5550Sstevel@tonic-gate oss->ss_onstack = ((oalt.ss_flags & SS_ONSTACK) != 0);
5560Sstevel@tonic-gate }
5570Sstevel@tonic-gate
5580Sstevel@tonic-gate return (0);
5590Sstevel@tonic-gate }
5600Sstevel@tonic-gate
5610Sstevel@tonic-gate void (*
ucbsignal(int s,void (* a)(int))5620Sstevel@tonic-gate ucbsignal(int s, void (*a)(int)))(int)
5630Sstevel@tonic-gate {
5640Sstevel@tonic-gate struct sigvec osv;
5650Sstevel@tonic-gate struct sigvec nsv;
5660Sstevel@tonic-gate static int mask[NSIG];
5670Sstevel@tonic-gate static int flags[NSIG];
5680Sstevel@tonic-gate
5690Sstevel@tonic-gate nsv.sv_handler = (void (*) (int, int, struct sigcontext *, char *)) a;
5700Sstevel@tonic-gate nsv.sv_mask = mask[s];
5710Sstevel@tonic-gate nsv.sv_flags = flags[s];
5720Sstevel@tonic-gate if (ucbsigvec(s, &nsv, &osv) < 0)
5730Sstevel@tonic-gate return (SIG_ERR);
5740Sstevel@tonic-gate if (nsv.sv_mask != osv.sv_mask || nsv.sv_flags != osv.sv_flags) {
5750Sstevel@tonic-gate mask[s] = nsv.sv_mask = osv.sv_mask;
5760Sstevel@tonic-gate flags[s] = nsv.sv_flags =
577*712Smuffin osv.sv_flags & ~(SV_RESETHAND|SV_INTERRUPT);
5780Sstevel@tonic-gate if (ucbsigvec(s, &nsv, (struct sigvec *)0) < 0)
5790Sstevel@tonic-gate return (SIG_ERR);
5800Sstevel@tonic-gate }
5810Sstevel@tonic-gate return ((void (*) (int)) osv.sv_handler);
5820Sstevel@tonic-gate }
5830Sstevel@tonic-gate
5840Sstevel@tonic-gate void (*
usignal(int s,void (* a)(int))5850Sstevel@tonic-gate usignal(int s, void (*a) (int)))(int)
5860Sstevel@tonic-gate {
5870Sstevel@tonic-gate return (ucbsignal(s, a));
5880Sstevel@tonic-gate }
5890Sstevel@tonic-gate
5900Sstevel@tonic-gate /*
5910Sstevel@tonic-gate * Set signal state to prevent restart of system calls
5920Sstevel@tonic-gate * after an instance of the indicated signal.
5930Sstevel@tonic-gate */
5940Sstevel@tonic-gate
5950Sstevel@tonic-gate int
_siginterrupt(int sig,int flag)5960Sstevel@tonic-gate _siginterrupt(int sig, int flag)
5970Sstevel@tonic-gate {
5980Sstevel@tonic-gate return (ucbsiginterrupt(sig, flag));
5990Sstevel@tonic-gate }
6000Sstevel@tonic-gate
6010Sstevel@tonic-gate int
ucbsiginterrupt(int sig,int flag)6020Sstevel@tonic-gate ucbsiginterrupt(int sig, int flag)
6030Sstevel@tonic-gate {
6040Sstevel@tonic-gate struct sigvec sv;
6050Sstevel@tonic-gate int ret;
6060Sstevel@tonic-gate
6070Sstevel@tonic-gate if ((ret = ucbsigvec(sig, 0, &sv)) < 0)
6080Sstevel@tonic-gate return (ret);
6090Sstevel@tonic-gate if (flag)
6100Sstevel@tonic-gate sv.sv_flags |= SV_INTERRUPT;
6110Sstevel@tonic-gate else
6120Sstevel@tonic-gate sv.sv_flags &= ~SV_INTERRUPT;
6130Sstevel@tonic-gate return (ucbsigvec(sig, &sv, 0));
6140Sstevel@tonic-gate }
615