ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SheepShaver/src/Unix/main_unix.cpp
(Generate patch)

Comparing SheepShaver/src/Unix/main_unix.cpp (file contents):
Revision 1.63 by gbeauche, 2005-06-08T12:12:50Z vs.
Revision 1.70 by gbeauche, 2005-07-06T04:58:34Z

# Line 67 | Line 67
67   *  ExecutePPC (or any function that might cause a mode switch). The signal
68   *  stack is restored before exiting the SIGUSR2 handler.
69   *
70 < *  There is apparently another problem when processing signals. In
71 < *  fullscreen mode, we get quick updates of the mouse position. This
72 < *  causes an increased number of calls to TriggerInterrupt(). And,
73 < *  since IRQ_NEST is not fully handled atomically, nested calls to
74 < *  ppc_interrupt() may cause stack corruption to eventually crash the
75 < *  emulator.
76 < *
77 < *  FIXME:
78 < *  The current solution is to allocate another signal stack when
79 < *  processing ppc_interrupt(). However, it may be better to detect
80 < *  the INTFLAG_ADB case and handle it specifically with some extra mutex?
70 > *  Note that POSIX standard says you can't modify the alternate
71 > *  signal stack while the process is executing on it. There is a
72 > *  hackaround though: we install a trampoline SIGUSR2 handler that
73 > *  sets up an alternate stack itself and calls the real handler.
74 > *  Then, when we call sigaltstack() there, we no longer get an EPERM,
75 > *  i.e. it now works.
76   *
77   *  TODO:
78   *    check if SIGSEGV handler works for all registers (including FP!)
# Line 114 | Line 109
109   #include "user_strings.h"
110   #include "vm_alloc.h"
111   #include "sigsegv.h"
112 + #include "sigregs.h"
113  
114   #define DEBUG 0
115   #include "debug.h"
# Line 158 | Line 154
154   // Interrupts in native mode?
155   #define INTERRUPTS_IN_NATIVE_MODE 1
156  
161 // Number of alternate stacks for signal handlers?
162 #define SIG_STACK_COUNT 4
163
157  
158   // Constants
159   const char ROM_FILE_NAME[] = "ROM";
# Line 175 | Line 168 | const uintptr RAM_BASE = 0x10000000;           //
168   const uint32 SIG_STACK_SIZE = 0x10000;          // Size of signal stack
169  
170  
178 #if !EMULATED_PPC
179 struct sigregs {
180        uint32 nip;
181        uint32 link;
182        uint32 ctr;
183        uint32 msr;
184        uint32 xer;
185        uint32 ccr;
186        uint32 gpr[32];
187 };
188
189 #if defined(__linux__)
190 #include <sys/ucontext.h>
191 #define MACHINE_REGISTERS(scp)  ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext.regs))
192
193 struct machine_regs : public pt_regs
194 {
195        u_long & cr()                           { return pt_regs::ccr; }
196        uint32 cr() const                       { return pt_regs::ccr; }
197        uint32 lr() const                       { return pt_regs::link; }
198        uint32 ctr() const                      { return pt_regs::ctr; }
199        uint32 xer() const                      { return pt_regs::xer; }
200        uint32 msr() const                      { return pt_regs::msr; }
201        uint32 dar() const                      { return pt_regs::dar; }
202        u_long & pc()                           { return pt_regs::nip; }
203        uint32 pc() const                       { return pt_regs::nip; }
204        u_long & gpr(int i)                     { return pt_regs::gpr[i]; }
205        uint32 gpr(int i) const         { return pt_regs::gpr[i]; }
206 };
207 #endif
208
209 #if defined(__NetBSD__)
210 #include <sys/ucontext.h>
211 #define MACHINE_REGISTERS(scp)  ((machine_regs *)&(((ucontext_t *)scp)->uc_mcontext))
212
213 struct machine_regs : public mcontext_t
214 {
215        long & cr()                                     { return __gregs[_REG_CR]; }
216        uint32 cr() const                       { return __gregs[_REG_CR]; }
217        uint32 lr() const                       { return __gregs[_REG_LR]; }
218        uint32 ctr() const                      { return __gregs[_REG_CTR]; }
219        uint32 xer() const                      { return __gregs[_REG_XER]; }
220        uint32 msr() const                      { return __gregs[_REG_MSR]; }
221        uint32 dar() const                      { return (uint32)(((siginfo_t *)(((unsigned long)this) - offsetof(ucontext_t, uc_mcontext))) - 1)->si_addr; } /* HACK */
222        long & pc()                                     { return __gregs[_REG_PC]; }
223        uint32 pc() const                       { return __gregs[_REG_PC]; }
224        long & gpr(int i)                       { return __gregs[_REG_R0 + i]; }
225        uint32 gpr(int i) const         { return __gregs[_REG_R0 + i]; }
226 };
227 #endif
228
229 #if defined(__APPLE__) && defined(__MACH__)
230 #include <sys/signal.h>
231 extern "C" int sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss);
232
233 #include <sys/ucontext.h>
234 #define MACHINE_REGISTERS(scp)  ((machine_regs *)(((ucontext_t *)scp)->uc_mcontext))
235
236 struct machine_regs : public mcontext
237 {
238        uint32 & cr()                           { return ss.cr; }
239        uint32 cr() const                       { return ss.cr; }
240        uint32 lr() const                       { return ss.lr; }
241        uint32 ctr() const                      { return ss.ctr; }
242        uint32 xer() const                      { return ss.xer; }
243        uint32 msr() const                      { return ss.srr1; }
244        uint32 dar() const                      { return es.dar; }
245        uint32 & pc()                           { return ss.srr0; }
246        uint32 pc() const                       { return ss.srr0; }
247        uint32 & gpr(int i)                     { return (&ss.r0)[i]; }
248        uint32 gpr(int i) const         { return (&ss.r0)[i]; }
249 };
250 #endif
251
252 static void build_sigregs(sigregs *srp, machine_regs *mrp)
253 {
254        srp->nip = mrp->pc();
255        srp->link = mrp->lr();
256        srp->ctr = mrp->ctr();
257        srp->msr = mrp->msr();
258        srp->xer = mrp->xer();
259        srp->ccr = mrp->cr();
260        for (int i = 0; i < 32; i++)
261                srp->gpr[i] = mrp->gpr(i);
262 }
263
264 static struct sigaltstack sig_stacks[SIG_STACK_COUNT];  // Stacks for signal handlers
265 static int sig_stack_id = 0;                                                    // Stack slot currently used
266
267 static inline int sig_stack_acquire(void)
268 {
269        if (sig_stack_id >= SIG_STACK_COUNT) {
270                printf("FATAL: signal stack overflow\n");
271                return -1;
272        }
273        return sigaltstack(&sig_stacks[sig_stack_id++], NULL);
274 }
275
276 static inline int sig_stack_release(void)
277 {
278        if (sig_stack_id <= 0) {
279                printf("FATAL: signal stack underflow\n");
280                return -1;
281        }
282        return sigaltstack(&sig_stacks[--sig_stack_id], NULL);
283 }
284 #endif
285
286
171   // Global variables (exported)
172   #if !EMULATED_PPC
173 < void *TOC;                              // Pointer to Thread Local Storage (r2)
174 < void *R13;                              // Pointer to .sdata section (r13 under Linux)
173 > void *TOC = NULL;               // Pointer to Thread Local Storage (r2)
174 > void *R13 = NULL;               // Pointer to .sdata section (r13 under Linux)
175   #endif
176   uint32 RAMBase;                 // Base address of Mac RAM
177   uint32 RAMSize;                 // Size of Mac RAM
# Line 340 | Line 224 | static uintptr sig_stack = 0;                          // Stac
224   #else
225   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
226   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
227 + static struct sigaltstack sig_stack;            // Stack for signal handlers
228 + static struct sigaltstack extra_stack;          // Stack for SIGSEGV inside interrupt handler
229   static bool emul_thread_fatal = false;          // Flag: MacOS thread crashed, tick thread shall dump debug output
230   static sigregs sigsegv_regs;                            // Register dump when crashed
231   static const char *crash_reason = NULL;         // Reason of the crash (SIGSEGV, SIGBUS, SIGILL)
# Line 365 | Line 251 | extern void init_emul_ppc(void);
251   extern void exit_emul_ppc(void);
252   sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
253   #else
254 < static void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
254 > extern "C" void sigusr2_handler_init(int sig, siginfo_t *sip, void *scp);
255 > extern "C" void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
256   static void sigsegv_handler(int sig, siginfo_t *sip, void *scp);
257   static void sigill_handler(int sig, siginfo_t *sip, void *scp);
258   #endif
# Line 565 | Line 452 | int main(int argc, char **argv)
452  
453   #if !EMULATED_PPC
454          // Create and install stacks for signal handlers
455 <        for (int i = 0; i < SIG_STACK_COUNT; i++) {
456 <                void *sig_stack = malloc(SIG_STACK_SIZE);
457 <                D(bug("Signal stack %d at %p\n", i, sig_stack));
458 <                if (sig_stack == NULL) {
459 <                        ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
573 <                        goto quit;
574 <                }
575 <                sig_stacks[i].ss_sp = sig_stack;
576 <                sig_stacks[i].ss_flags = 0;
577 <                sig_stacks[i].ss_size = SIG_STACK_SIZE;
455 >        sig_stack.ss_sp = malloc(SIG_STACK_SIZE);
456 >        D(bug("Signal stack at %p\n", sig_stack.ss_sp));
457 >        if (sig_stack.ss_sp == NULL) {
458 >                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
459 >                goto quit;
460          }
461 <        if (sig_stack_acquire() < 0) {
461 >        sig_stack.ss_flags = 0;
462 >        sig_stack.ss_size = SIG_STACK_SIZE;
463 >        if (sigaltstack(&sig_stack, NULL) < 0) {
464                  sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
465                  ErrorAlert(str);
466                  goto quit;
467          }
468 +        extra_stack.ss_sp = malloc(SIG_STACK_SIZE);
469 +        D(bug("Extra stack at %p\n", extra_stack.ss_sp));
470 +        if (extra_stack.ss_sp == NULL) {
471 +                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
472 +                goto quit;
473 +        }
474 +        extra_stack.ss_flags = 0;
475 +        extra_stack.ss_size = SIG_STACK_SIZE;
476   #endif
477  
478   #if !EMULATED_PPC
# Line 779 | Line 671 | int main(int argc, char **argv)
671          case 0x8000:                            // 7450
672          case 0x8001:                            // 7455
673          case 0x8002:                            // 7457
674 +        case 0x8003:                            // 7447A
675          case 0x0039:                            //  970
676                  PVR = 0x000c0000;               // 7400
677                  break;
# Line 971 | Line 864 | int main(int argc, char **argv)
864   #if !EMULATED_PPC
865          // Install interrupt signal handler
866          sigemptyset(&sigusr2_action.sa_mask);
867 <        sigusr2_action.sa_sigaction = sigusr2_handler;
867 >        sigusr2_action.sa_sigaction = sigusr2_handler_init;
868          sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
869   #ifdef HAVE_SIGNAL_SA_RESTORER
870          sigusr2_action.sa_restorer = NULL;
# Line 1034 | Line 927 | static void Quit(void)
927          sigaction(SIGILL, &sigill_action, NULL);
928  
929          // Delete stacks for signal handlers
930 <        for (int i = 0; i < SIG_STACK_COUNT; i++) {
931 <                void *sig_stack = sig_stacks[i].ss_sp;
932 <                if (sig_stack)
933 <                        free(sig_stack);
1041 <        }
930 >        if (sig_stack.ss_sp)
931 >                free(sig_stack.ss_sp);
932 >        if (extra_stack.ss_sp)
933 >                free(extra_stack.ss_sp);
934   #endif
935  
936          // Deinitialize everything
# Line 1411 | Line 1303 | static void *tick_func(void *arg)
1303          }
1304  
1305          uint64 end = GetTicks_usec();
1306 <        D(bug("%Ld ticks in %Ld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1306 >        D(bug("%lld ticks in %lld usec = %f ticks/sec\n", ticks, end - start, ticks * 1000000.0 / (end - start)));
1307          return NULL;
1308   }
1309  
# Line 1535 | Line 1427 | void B2_delete_mutex(B2_mutex *mutex)
1427   #if !EMULATED_PPC
1428   void TriggerInterrupt(void)
1429   {
1430 <        if (ready_for_signals)
1430 >        if (ready_for_signals) {
1431 >                idle_resume();
1432                  pthread_kill(emul_thread, SIGUSR2);
1433 +        }
1434   }
1435   #endif
1436  
# Line 1591 | Line 1485 | void EnableInterrupt(void)
1485   */
1486  
1487   #if !EMULATED_PPC
1488 < static void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
1488 > void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
1489   {
1490          machine_regs *r = MACHINE_REGISTERS(scp);
1491  
1598 #ifdef USE_SDL_VIDEO
1599        // We must fill in the events queue in the same thread that did call SDL_SetVideoMode()
1600        SDL_PumpEvents();
1601 #endif
1602
1603        // Do nothing if interrupts are disabled
1604        if (*(int32 *)XLM_IRQ_NEST > 0)
1605                return;
1606
1492   #ifdef SYSTEM_CLOBBERS_R2
1493          // Restore pointer to Thread Local Storage
1494          set_r2(TOC);
# Line 1613 | Line 1498 | static void sigusr2_handler(int sig, sig
1498          set_r13(R13);
1499   #endif
1500  
1501 + #ifdef USE_SDL_VIDEO
1502 +        // We must fill in the events queue in the same thread that did call SDL_SetVideoMode()
1503 +        SDL_PumpEvents();
1504 + #endif
1505 +
1506 +        // Do nothing if interrupts are disabled
1507 +        if (*(int32 *)XLM_IRQ_NEST > 0)
1508 +                return;
1509 +
1510          // Disable MacOS stack sniffer
1511          WriteMacInt32(0x110, 0);
1512  
# Line 1629 | Line 1523 | static void sigusr2_handler(int sig, sig
1523                          // 68k emulator inactive, in nanokernel?
1524                          if (r->gpr(1) != KernelDataAddr) {
1525  
1526 <                                // Set extra stack for nested interrupts
1527 <                                sig_stack_acquire();
1526 >                                // Set extra stack for SIGSEGV handler
1527 >                                sigaltstack(&extra_stack, NULL);
1528                                  
1529                                  // Prepare for 68k interrupt level 1
1530                                  WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
# Line 1643 | Line 1537 | static void sigusr2_handler(int sig, sig
1537                                  else
1538                                          ppc_interrupt(ROM_BASE + 0x312a3c, KernelDataAddr);
1539  
1540 <                                // Reset normal signal stack
1541 <                                sig_stack_release();
1540 >                                // Reset normal stack
1541 >                                sigaltstack(&sig_stack, NULL);
1542                          }
1543                          break;
1544   #endif
# Line 1655 | Line 1549 | static void sigusr2_handler(int sig, sig
1549                          if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1550  
1551                                  // Set extra stack for SIGSEGV handler
1552 <                                sig_stack_acquire();
1552 >                                sigaltstack(&extra_stack, NULL);
1553   #if 1
1554                                  // Execute full 68k interrupt routine
1555                                  M68kRegisters r;
# Line 1681 | Line 1575 | static void sigusr2_handler(int sig, sig
1575                                          }
1576                                  }
1577   #endif
1578 <                                // Reset normal signal stack
1579 <                                sig_stack_release();
1578 >                                // Reset normal stack
1579 >                                sigaltstack(&sig_stack, NULL);
1580                          }
1581                          break;
1582   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines