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.64 by gbeauche, 2005-06-23T16:23:31Z vs.
Revision 1.65 by gbeauche, 2005-06-28T16:47:32Z

# 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 158 | Line 153
153   // Interrupts in native mode?
154   #define INTERRUPTS_IN_NATIVE_MODE 1
155  
161 // Number of alternate stacks for signal handlers?
162 #define SIG_STACK_COUNT 4
163
156  
157   // Constants
158   const char ROM_FILE_NAME[] = "ROM";
# Line 260 | Line 252 | static void build_sigregs(sigregs *srp,
252          for (int i = 0; i < 32; i++)
253                  srp->gpr[i] = mrp->gpr(i);
254   }
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 }
255   #endif
256  
257  
# Line 340 | Line 311 | static uintptr sig_stack = 0;                          // Stac
311   #else
312   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
313   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
314 + static struct sigaltstack sig_stack;            // Stack for signal handlers
315 + static struct sigaltstack extra_stack;          // Stack for SIGSEGV inside interrupt handler
316   static bool emul_thread_fatal = false;          // Flag: MacOS thread crashed, tick thread shall dump debug output
317   static sigregs sigsegv_regs;                            // Register dump when crashed
318   static const char *crash_reason = NULL;         // Reason of the crash (SIGSEGV, SIGBUS, SIGILL)
# Line 365 | Line 338 | extern void init_emul_ppc(void);
338   extern void exit_emul_ppc(void);
339   sigsegv_return_t sigsegv_handler(sigsegv_address_t, sigsegv_address_t);
340   #else
341 < static void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
341 > extern "C" void sigusr2_handler_init(int sig, siginfo_t *sip, void *scp);
342 > extern "C" void sigusr2_handler(int sig, siginfo_t *sip, void *scp);
343   static void sigsegv_handler(int sig, siginfo_t *sip, void *scp);
344   static void sigill_handler(int sig, siginfo_t *sip, void *scp);
345   #endif
# Line 565 | Line 539 | int main(int argc, char **argv)
539  
540   #if !EMULATED_PPC
541          // Create and install stacks for signal handlers
542 <        for (int i = 0; i < SIG_STACK_COUNT; i++) {
543 <                void *sig_stack = malloc(SIG_STACK_SIZE);
544 <                D(bug("Signal stack %d at %p\n", i, sig_stack));
545 <                if (sig_stack == NULL) {
546 <                        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;
542 >        sig_stack.ss_sp = malloc(SIG_STACK_SIZE);
543 >        D(bug("Signal stack at %p\n", sig_stack.ss_sp));
544 >        if (sig_stack.ss_sp == NULL) {
545 >                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
546 >                goto quit;
547          }
548 <        if (sig_stack_acquire() < 0) {
548 >        sig_stack.ss_flags = 0;
549 >        sig_stack.ss_size = SIG_STACK_SIZE;
550 >        if (sigaltstack(&sig_stack, NULL) < 0) {
551                  sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
552                  ErrorAlert(str);
553                  goto quit;
554          }
555 +        extra_stack.ss_sp = malloc(SIG_STACK_SIZE);
556 +        D(bug("Extra stack at %p\n", extra_stack.ss_sp));
557 +        if (extra_stack.ss_sp == NULL) {
558 +                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
559 +                goto quit;
560 +        }
561 +        extra_stack.ss_flags = 0;
562 +        extra_stack.ss_size = SIG_STACK_SIZE;
563   #endif
564  
565   #if !EMULATED_PPC
# Line 971 | Line 950 | int main(int argc, char **argv)
950   #if !EMULATED_PPC
951          // Install interrupt signal handler
952          sigemptyset(&sigusr2_action.sa_mask);
953 <        sigusr2_action.sa_sigaction = sigusr2_handler;
953 >        sigusr2_action.sa_sigaction = sigusr2_handler_init;
954          sigusr2_action.sa_flags = SA_ONSTACK | SA_RESTART | SA_SIGINFO;
955   #ifdef HAVE_SIGNAL_SA_RESTORER
956          sigusr2_action.sa_restorer = NULL;
# Line 1034 | Line 1013 | static void Quit(void)
1013          sigaction(SIGILL, &sigill_action, NULL);
1014  
1015          // Delete stacks for signal handlers
1016 <        for (int i = 0; i < SIG_STACK_COUNT; i++) {
1017 <                void *sig_stack = sig_stacks[i].ss_sp;
1018 <                if (sig_stack)
1019 <                        free(sig_stack);
1041 <        }
1016 >        if (sig_stack.ss_sp)
1017 >                free(sig_stack.ss_sp);
1018 >        if (extra_stack.ss_sp)
1019 >                free(extra_stack.ss_sp);
1020   #endif
1021  
1022          // Deinitialize everything
# Line 1591 | Line 1569 | void EnableInterrupt(void)
1569   */
1570  
1571   #if !EMULATED_PPC
1572 < static void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
1572 > void sigusr2_handler(int sig, siginfo_t *sip, void *scp)
1573   {
1574          machine_regs *r = MACHINE_REGISTERS(scp);
1575  
# Line 1629 | Line 1607 | static void sigusr2_handler(int sig, sig
1607                          // 68k emulator inactive, in nanokernel?
1608                          if (r->gpr(1) != KernelDataAddr) {
1609  
1610 <                                // Set extra stack for nested interrupts
1611 <                                sig_stack_acquire();
1610 >                                // Set extra stack for SIGSEGV handler
1611 >                                sigaltstack(&extra_stack, NULL);
1612                                  
1613                                  // Prepare for 68k interrupt level 1
1614                                  WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
# Line 1643 | Line 1621 | static void sigusr2_handler(int sig, sig
1621                                  else
1622                                          ppc_interrupt(ROM_BASE + 0x312a3c, KernelDataAddr);
1623  
1624 <                                // Reset normal signal stack
1625 <                                sig_stack_release();
1624 >                                // Reset normal stack
1625 >                                sigaltstack(&sig_stack, NULL);
1626                          }
1627                          break;
1628   #endif
# Line 1655 | Line 1633 | static void sigusr2_handler(int sig, sig
1633                          if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1634  
1635                                  // Set extra stack for SIGSEGV handler
1636 <                                sig_stack_acquire();
1636 >                                sigaltstack(&extra_stack, NULL);
1637   #if 1
1638                                  // Execute full 68k interrupt routine
1639                                  M68kRegisters r;
# Line 1681 | Line 1659 | static void sigusr2_handler(int sig, sig
1659                                          }
1660                                  }
1661   #endif
1662 <                                // Reset normal signal stack
1663 <                                sig_stack_release();
1662 >                                // Reset normal stack
1663 >                                sigaltstack(&sig_stack, NULL);
1664                          }
1665                          break;
1666   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines