Home | History | Annotate | Download | only in sparc
      1 /*
      2  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
      7 /*	  All Rights Reserved  	*/
      8 
      9 /*
     10  * Copyright (c) 1980 Regents of the University of California.
     11  * All rights reserved. The Berkeley Software License Agreement
     12  * specifies the terms and conditions for redistribution.
     13  */
     14 
     15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     16 
     17 /*
     18  * 4.3BSD signal compatibility functions
     19  *
     20  * the implementation interprets signal masks equal to -1 as "all of the
     21  * signals in the signal set", thereby allowing signals with numbers
     22  * above 32 to be blocked when referenced in code such as:
     23  *
     24  *	for (i = 0; i < NSIG; i++)
     25  *		mask |= sigmask(i)
     26  */
     27 
     28 #include <sys/types.h>
     29 #include <sys/siginfo.h>
     30 #include <sys/ucontext.h>
     31 #include <signal.h>
     32 #include "signal.h"
     33 #include <errno.h>
     34 #include <stdio.h>
     35 
     36 #define set2mask(setp) ((setp)->__sigbits[0])
     37 #define mask2set(mask, setp) \
     38 	((mask) == -1 ? sigfillset(setp) : sigemptyset(setp), (((setp)->__sigbits[0]) = (mask)))
     39 
     40 void (*_siguhandler[NSIG])() = { 0 };
     41 
     42 /*
     43  * sigstack is emulated with sigaltstack by guessing an appropriate
     44  * value for the stack size - on machines that have stacks that grow
     45  * upwards, the ss_sp arguments for both functions mean the same thing,
     46  * (the initial stack pointer sigstack() is also the stack base
     47  * sigaltstack()), so a "very large" value should be chosen for the
     48  * stack size - on machines that have stacks that grow downwards, the
     49  * ss_sp arguments mean opposite things, so 0 should be used (hopefully
     50  * these machines don't have hardware stack bounds registers that pay
     51  * attention to sigaltstack()'s size argument.
     52  */
     53 
     54 #ifdef sun
     55 #define SIGSTACKSIZE	0
     56 #endif
     57 
     58 
     59 /*
     60  * sigvechandler is the real signal handler installed for all
     61  * signals handled in the 4.3BSD compatibility interface - it translates
     62  * SVR4 signal hander arguments into 4.3BSD signal handler arguments
     63  * and then calls the real handler
     64  */
     65 
     66 static void
     67 sigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp)
     68 {
     69 	struct sigcontext sc;
     70 	int code;
     71 	char *addr;
     72 	int i, j;
     73 	int gwinswitch = 0;
     74 
     75 	sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0);
     76 	sc.sc_mask = set2mask(&ucp->uc_sigmask);
     77 
     78 	/*
     79 	 * Machine dependent code begins
     80 	 */
     81 	sc.sc_sp = ucp->uc_mcontext.gregs[REG_O6];
     82 	sc.sc_pc = ucp->uc_mcontext.gregs[REG_PC];
     83 	sc.sc_npc = ucp->uc_mcontext.gregs[REG_nPC];
     84 	sc.sc_psr = ucp->uc_mcontext.gregs[REG_PSR];
     85 	sc.sc_g1 = ucp->uc_mcontext.gregs[REG_G1];
     86 	sc.sc_o0 = ucp->uc_mcontext.gregs[REG_O0];
     87 	if (ucp->uc_mcontext.gwins != (gwindows_t *)0) {
     88 		gwinswitch = 1;
     89 		sc.sc_wbcnt = ucp->uc_mcontext.gwins->wbcnt;
     90 		for (i = 0; i < MAXWINDOW; i++) {
     91 			for (j = 0; j < 16; j++)
     92 				sc.sc_spbuf[i][j] = (int)ucp->uc_mcontext.gwins->spbuf[j];
     93 			for (j = 0; j < 8; j++)
     94 				sc.sc_wbuf[i][j] = ucp->uc_mcontext.gwins->wbuf[i].rw_local[j];
     95 			for (j = 0; j < 8; j++)
     96 				sc.sc_wbuf[i][j+8] = ucp->uc_mcontext.gwins->wbuf[i].rw_in[j];
     97 		}
     98 	}
     99 	/*
    100 	 * Machine dependent code ends
    101 	 */
    102 
    103 	if (sip != NULL)
    104 		if ((code = sip->si_code) == BUS_OBJERR)
    105 			code = SEGV_MAKE_ERR(sip->si_errno);
    106 
    107 	if (sig == SIGILL || sig == SIGFPE || sig == SIGSEGV || sig == SIGBUS)
    108 		if (sip != NULL)
    109 			addr = (char *)sip->si_addr;
    110 	else
    111 		addr = SIG_NOADDR;
    112 
    113 	(*_siguhandler[sig])(sig, code, &sc, addr);
    114 
    115 	if (sc.sc_onstack)
    116 		ucp->uc_stack.ss_flags |= SS_ONSTACK;
    117 	else
    118 		ucp->uc_stack.ss_flags &= ~SS_ONSTACK;
    119 	mask2set(sc.sc_mask, &ucp->uc_sigmask);
    120 
    121 	/*
    122 	 * Machine dependent code begins
    123 	 */
    124 	ucp->uc_mcontext.gregs[REG_O6] = sc.sc_sp;
    125 	ucp->uc_mcontext.gregs[REG_PC] = sc.sc_pc;
    126 	ucp->uc_mcontext.gregs[REG_nPC] = sc.sc_npc;
    127 	ucp->uc_mcontext.gregs[REG_PSR] = sc.sc_psr;
    128 	ucp->uc_mcontext.gregs[REG_G1] = sc.sc_g1;
    129 	ucp->uc_mcontext.gregs[REG_O0] = sc.sc_o0;
    130 	if (gwinswitch == 1) {
    131 		ucp->uc_mcontext.gwins->wbcnt = sc.sc_wbcnt;
    132 		for (i = 0; i < MAXWINDOW; i++) {
    133 			for (j = 0; j < 16; j++)
    134 				ucp->uc_mcontext.gwins->spbuf[j] = (greg_t *)sc.sc_spbuf[i][j];
    135 			for (j = 0; j < 8; j++)
    136 				ucp->uc_mcontext.gwins->wbuf[i].rw_local[j] = sc.sc_wbuf[i][j];
    137 			for (j = 0; j < 8; j++)
    138 				ucp->uc_mcontext.gwins->wbuf[i].rw_in[j] = sc.sc_wbuf[i][j+8];
    139 		}
    140 	}
    141 	/*
    142 	 * Machine dependent code ends
    143 	 */
    144 
    145 	setcontext (ucp);
    146 }
    147 
    148 int
    149 sigsetmask(int mask)
    150 {
    151 	sigset_t oset;
    152 	sigset_t nset;
    153 
    154 	(void) sigprocmask(0, (sigset_t *)0, &nset);
    155 	mask2set(mask, &nset);
    156 	(void) sigprocmask(SIG_SETMASK, &nset, &oset);
    157 	return set2mask(&oset);
    158 }
    159 
    160 int
    161 sigblock(int mask)
    162 {
    163 	sigset_t oset;
    164 	sigset_t nset;
    165 
    166 	(void) sigprocmask(0, (sigset_t *)0, &nset);
    167 	mask2set(mask, &nset);
    168 	(void) sigprocmask(SIG_BLOCK, &nset, &oset);
    169 	return set2mask(&oset);
    170 }
    171 
    172 int
    173 sigpause(int mask)
    174 {
    175 	sigset_t set;
    176 
    177 	(void) sigprocmask(0, (sigset_t *)0, &set);
    178 	mask2set(mask, &set);
    179 	return (sigsuspend(&set));
    180 }
    181 
    182 int
    183 sigvec(int sig, struct sigvec *nvec, struct sigvec *ovec)
    184 {
    185         struct sigaction nact;
    186         struct sigaction oact;
    187         struct sigaction *nactp;
    188         void (*ohandler)(), (*nhandler)();
    189 
    190         if (sig <= 0 || sig >= NSIG) {
    191                 errno = EINVAL;
    192                 return -1;
    193         }
    194 
    195         ohandler = _siguhandler[sig];
    196 
    197         if (nvec) {
    198 		_sigaction(sig, (struct sigaction *)0, &nact);
    199                 nhandler = nvec->sv_handler;
    200                 _siguhandler[sig] = nhandler;
    201                 if (nhandler != SIG_DFL && nhandler != SIG_IGN)
    202                         nact.sa_handler = (void (*)())sigvechandler;
    203 		else
    204 			nact.sa_handler = nhandler;
    205 		mask2set(nvec->sv_mask, &nact.sa_mask);
    206 		/*
    207 		if ( sig == SIGTSTP || sig == SIGSTOP )
    208 			nact.sa_handler = SIG_DFL; 	*/
    209 		nact.sa_flags = SA_SIGINFO;
    210 		if (!(nvec->sv_flags & SV_INTERRUPT))
    211 			nact.sa_flags |= SA_RESTART;
    212 		if (nvec->sv_flags & SV_RESETHAND)
    213 			nact.sa_flags |= SA_RESETHAND;
    214 		if (nvec->sv_flags & SV_ONSTACK)
    215 			nact.sa_flags |= SA_ONSTACK;
    216 		nactp = &nact;
    217         } else
    218 		nactp = (struct sigaction *)0;
    219 
    220         if (_sigaction(sig, nactp, &oact) < 0) {
    221                 _siguhandler[sig] = ohandler;
    222                 return -1;
    223         }
    224 
    225         if (ovec) {
    226 		if (oact.sa_handler == SIG_DFL || oact.sa_handler == SIG_IGN)
    227 			ovec->sv_handler = oact.sa_handler;
    228 		else
    229 			ovec->sv_handler = ohandler;
    230 		ovec->sv_mask = set2mask(&oact.sa_mask);
    231 		ovec->sv_flags = 0;
    232 		if (oact.sa_flags & SA_ONSTACK)
    233 			ovec->sv_flags |= SV_ONSTACK;
    234 		if (oact.sa_flags & SA_RESETHAND)
    235 			ovec->sv_flags |= SV_RESETHAND;
    236 		if (!(oact.sa_flags & SA_RESTART))
    237 			ovec->sv_flags |= SV_INTERRUPT;
    238 	}
    239 
    240         return 0;
    241 }
    242 
    243 
    244 void (*
    245 signal(int s, void (*a)()))()
    246 {
    247         struct sigvec osv;
    248 	struct sigvec nsv;
    249         static int mask[NSIG];
    250         static int flags[NSIG];
    251 
    252 	nsv.sv_handler = a;
    253 	nsv.sv_mask = mask[s];
    254 	nsv.sv_flags = flags[s];
    255         if (sigvec(s, &nsv, &osv) < 0)
    256                 return (SIG_ERR);
    257         if (nsv.sv_mask != osv.sv_mask || nsv.sv_flags != osv.sv_flags) {
    258                 mask[s] = nsv.sv_mask = osv.sv_mask;
    259                 flags[s] = nsv.sv_flags = osv.sv_flags & ~SV_RESETHAND;
    260                 if (sigvec(s, &nsv, (struct sigvec *)0) < 0)
    261                         return (SIG_ERR);
    262         }
    263         return (osv.sv_handler);
    264 }
    265