Release 960606
[wine/multimedia.git] / loader / signal.c
blobc0f422f6fcaeb9fd487667a9f30b69509151949e
1 #ifndef WINELIB
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <signal.h>
5 #include <string.h>
6 #include <errno.h>
7 #include <time.h>
8 #include <setjmp.h>
10 #include <sys/time.h>
11 #include <sys/timeb.h>
13 #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__svr4__) || defined(_SCO_DS)
14 #ifndef _SCO_DS
15 #include <sys/syscall.h>
16 #endif
17 #include <sys/param.h>
18 #else
19 #include <syscall.h>
20 #endif
22 #include "debugger.h"
23 #include "miscemu.h"
24 #include "registers.h"
25 #include "win.h"
27 #if !defined(BSD4_4) || defined(linux) || defined(__FreeBSD__)
28 char * cstack[4096];
29 #endif
31 #ifdef linux
32 extern void ___sig_restore();
33 extern void ___masksig_restore();
35 /* Similar to the sigaction function in libc, except it leaves alone the
36 restorer field */
38 static int
39 wine_sigaction(int sig,struct sigaction * new, struct sigaction * old)
41 __asm__("int $0x80":"=a" (sig)
42 :"0" (SYS_sigaction),"b" (sig),"c" (new),"d" (old));
43 if (sig>=0)
44 return 0;
45 errno = -sig;
46 return -1;
48 #endif
51 /**********************************************************************
52 * wine_timer
54 * SIGALRM handler.
56 #ifdef linux
57 static void wine_timer(int signal, struct sigcontext_struct context_struct)
59 #elif defined(__svr4__)
60 static void wine_timer(int signal, void *siginfo, ucontext_t *context)
62 #else
63 static void wine_timer(int signal, int code, struct sigcontext *context)
65 #endif
66 /* Should do real-time timers here */
68 DOSMEM_Tick();
72 /**********************************************************************
73 * win_fault
75 * Segfault handler.
77 #ifdef linux
78 static void win_fault(int signal, struct sigcontext_struct context_struct)
80 struct sigcontext_struct *context = &context_struct;
81 #elif defined(__svr4__) || defined(_SCO_DS)
82 static void win_fault(int signal, void *siginfo, ucontext_t *context)
84 #else
85 static void win_fault(int signal, int code, struct sigcontext *context)
87 #endif
88 if (signal == SIGTRAP)
90 /* If SIGTRAP not caused by breakpoint or single step
91 don't jump into the debugger */
92 if (!(EFL_reg(context) & STEP_FLAG))
94 DBG_ADDR addr;
95 addr.seg = CS_reg(context);
96 addr.off = EIP_reg(context) - 1;
97 if (DEBUG_FindBreakpoint(&addr) == -1) return;
100 else if (signal != SIGHUP)
102 if (CS_reg(context) == WINE_CODE_SELECTOR)
104 fprintf(stderr, "Segmentation fault in Wine program (%x:%lx)."
105 " Please debug.\n",
106 CS_reg(context), EIP_reg(context) );
108 else
110 if (INSTR_EmulateInstruction( context )) return;
111 fprintf( stderr, "Segmentation fault in Windows program %x:%lx.\n",
112 CS_reg(context), EIP_reg(context) );
116 wine_debug( signal, context ); /* Enter our debugger */
120 /**********************************************************************
121 * SIGNAL_SetHandler
123 static void SIGNAL_SetHandler( int sig, void (*func)() )
125 int ret;
126 struct sigaction sig_act;
128 #ifdef linux
129 sig_act.sa_handler = func;
130 sig_act.sa_flags = SA_RESTART | SA_NOMASK;
131 /* Point to the top of the stack, minus 4 just in case, and make
132 it aligned */
133 sig_act.sa_restorer =
134 (void (*)()) (((unsigned int)(cstack) + sizeof(cstack) - 4) & ~3);
135 ret = wine_sigaction( sig, &sig_act, NULL );
136 #endif /* linux */
138 #if defined(__NetBSD__) || defined(__FreeBSD__)
139 sigset_t sig_mask;
140 sigemptyset(&sig_mask);
141 sig_act.sa_handler = func;
142 sig_act.sa_flags = SA_ONSTACK;
143 sig_act.sa_mask = sig_mask;
144 ret = sigaction( sig, &sig_act, NULL );
145 #endif /* __FreeBSD__ || __NetBSD__ */
147 #if defined (__svr4__) || defined(_SCO_DS)
148 sigset_t sig_mask;
149 sigemptyset(&sig_mask);
150 sig_act.sa_handler = func;
151 sig_act.sa_flags = SA_ONSTACK | SA_SIGINFO;
152 sig_act.sa_mask = sig_mask;
153 ret = sigaction( sig, &sig_act, NULL );
154 #endif /* __svr4__ || _SCO_DS */
156 if (ret < 0)
158 perror( "sigaction" );
159 exit(1);
163 extern void stop_wait(int a);
166 /**********************************************************************
167 * init_wine_signals
169 void init_wine_signals(void)
171 #if defined(__NetBSD__) || defined(__FreeBSD__)
172 struct sigaltstack ss;
174 if ((ss.ss_sp = malloc(MINSIGSTKSZ)) == NULL) {
175 fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
176 MINSIGSTKSZ);
177 exit(1);
179 ss.ss_size = MINSIGSTKSZ;
180 ss.ss_flags = 0;
181 if (sigaltstack(&ss, NULL) < 0) {
182 perror("sigstack");
183 exit(1);
185 #endif /* __FreeBSD__ || __NetBSD__ */
187 #if defined (__svr4__) || defined(_SCO_DS)
188 struct sigaltstack ss;
190 if ((ss.ss_sp = malloc(SIGSTKSZ) ) == NULL) {
191 fprintf(stderr, "Unable to allocate signal stack (%d bytes)\n",
192 SIGSTKSZ);
193 exit(1);
195 ss.ss_size = SIGSTKSZ;
196 ss.ss_flags = 0;
197 if (sigaltstack(&ss, NULL) < 0) {
198 perror("sigstack");
199 exit(1);
201 #endif /* __svr4__ || _SCO_DS */
203 SIGNAL_SetHandler( SIGALRM, (void (*)())wine_timer );
204 SIGNAL_SetHandler( SIGSEGV, (void (*)())win_fault );
205 SIGNAL_SetHandler( SIGILL, (void (*)())win_fault );
206 SIGNAL_SetHandler( SIGFPE, (void (*)())win_fault );
207 SIGNAL_SetHandler( SIGTRAP, (void (*)())win_fault ); /* For debugger */
208 SIGNAL_SetHandler( SIGHUP, (void (*)())win_fault ); /* For forced break */
209 #ifdef SIGBUS
210 SIGNAL_SetHandler( SIGBUS, (void (*)())win_fault );
211 #endif
212 #ifdef CONFIG_IPC
213 SIGNAL_SetHandler( SIGUSR2, (void (*)())stop_wait ); /* For IPC */
214 #endif
218 /**********************************************************************
219 * SIGNAL_StartBIOSTimer
221 * Start the BIOS tick timer.
223 void SIGNAL_StartBIOSTimer(void)
225 struct itimerval vt_timer;
226 static int timer_started = 0;
228 if (timer_started) return;
229 timer_started = 1;
230 vt_timer.it_interval.tv_sec = 0;
231 vt_timer.it_interval.tv_usec = 54929;
232 vt_timer.it_value = vt_timer.it_interval;
234 setitimer(ITIMER_REAL, &vt_timer, NULL);
237 #endif /* ifndef WINELIB */