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.32 by gbeauche, 2004-04-06T19:47:56Z vs.
Revision 1.33 by gbeauche, 2004-04-14T20:25:26Z

# Line 65 | Line 65
65   *  ExecutePPC (or any function that might cause a mode switch). The signal
66   *  stack is restored before exiting the SIGUSR2 handler.
67   *
68 + *  There is apparently another problem when processing signals. In
69 + *  fullscreen mode, we get quick updates of the mouse position. This
70 + *  causes an increased number of calls to TriggerInterrupt(). And,
71 + *  since IRQ_NEST is not fully handled atomically, nested calls to
72 + *  ppc_interrupt() may cause stack corruption to eventually crash the
73 + *  emulator.
74 + *
75 + *  FIXME:
76 + *  The current solution is to allocate another signal stack when
77 + *  processing ppc_interrupt(). However, it may be better to detect
78 + *  the INTFLAG_ADB case and handle it specifically with some extra mutex?
79 + *
80   *  TODO:
81   *    check if SIGSEGV handler works for all registers (including FP!)
82   */
# Line 144 | Line 156
156   // Interrupts in native mode?
157   #define INTERRUPTS_IN_NATIVE_MODE 1
158  
159 + // Number of alternate stacks for signal handlers?
160 + #define SIG_STACK_COUNT 4
161 +
162  
163   // Constants
164   const char ROM_FILE_NAME[] = "ROM";
# Line 218 | Line 233 | static void build_sigregs(sigregs *srp,
233          for (int i = 0; i < 32; i++)
234                  srp->gpr[i] = mrp->gpr(i);
235   }
236 +
237 + static struct sigaltstack sig_stacks[SIG_STACK_COUNT];  // Stacks for signal handlers
238 + static int sig_stack_id = 0;                                                    // Stack slot currently used
239 +
240 + static inline void sig_stack_acquire(void)
241 + {
242 +        if (++sig_stack_id == SIG_STACK_COUNT) {
243 +                printf("FATAL: signal stack overflow\n");
244 +                return;
245 +        }
246 +        sigaltstack(&sig_stacks[sig_stack_id], NULL);
247 + }
248 +
249 + static inline void sig_stack_release(void)
250 + {
251 +        if (--sig_stack_id < 0) {
252 +                printf("FATAL: signal stack underflow\n");
253 +                return;
254 +        }
255 +        sigaltstack(&sig_stacks[sig_stack_id], NULL);
256 + }
257   #endif
258  
259  
# Line 266 | Line 302 | static uintptr sig_stack = 0;                          // Stac
302   #else
303   static struct sigaction sigsegv_action;         // Data access exception signal (of emulator thread)
304   static struct sigaction sigill_action;          // Illegal instruction signal (of emulator thread)
269 static void *sig_stack = NULL;                          // Stack for signal handlers
270 static void *extra_stack = NULL;                        // Stack for SIGSEGV inside interrupt handler
305   static bool emul_thread_fatal = false;          // Flag: MacOS thread crashed, tick thread shall dump debug output
306   static sigregs sigsegv_regs;                            // Register dump when crashed
307   static const char *crash_reason = NULL;         // Reason of the crash (SIGSEGV, SIGBUS, SIGILL)
# Line 809 | Line 843 | int main(int argc, char **argv)
843  
844   #if !EMULATED_PPC
845          // Create and install stacks for signal handlers
846 <        sig_stack = malloc(SIG_STACK_SIZE);
847 <        D(bug("Signal stack at %p\n", sig_stack));
848 <        if (sig_stack == NULL) {
849 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
850 <                goto quit;
851 <        }
852 <        extra_stack = malloc(SIG_STACK_SIZE);
853 <        D(bug("Extra stack at %p\n", extra_stack));
854 <        if (extra_stack == NULL) {
855 <                ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
822 <                goto quit;
846 >        for (int i = 0; i < SIG_STACK_COUNT; i++) {
847 >                void *sig_stack = malloc(SIG_STACK_SIZE);
848 >                D(bug("Signal stack %d at %p\n", i, sig_stack));
849 >                if (sig_stack == NULL) {
850 >                        ErrorAlert(GetString(STR_NOT_ENOUGH_MEMORY_ERR));
851 >                        goto quit;
852 >                }
853 >                sig_stacks[i].ss_sp = sig_stack;
854 >                sig_stacks[i].ss_flags = 0;
855 >                sig_stacks[i].ss_size = SIG_STACK_SIZE;
856          }
857 <        struct sigaltstack new_stack;
858 <        new_stack.ss_sp = sig_stack;
826 <        new_stack.ss_flags = 0;
827 <        new_stack.ss_size = SIG_STACK_SIZE;
828 <        if (sigaltstack(&new_stack, NULL) < 0) {
857 >        sig_stack_id = 0;
858 >        if (sigaltstack(&sig_stacks[0], NULL) < 0) {
859                  sprintf(str, GetString(STR_SIGALTSTACK_ERR), strerror(errno));
860                  ErrorAlert(str);
861                  goto quit;
# Line 929 | Line 959 | static void Quit(void)
959          sigill_action.sa_handler = SIG_DFL;
960          sigill_action.sa_flags = 0;
961          sigaction(SIGILL, &sigill_action, NULL);
962 +
963 +        // Delete stacks for signal handlers
964 +        for (int i = 0; i < SIG_STACK_COUNT; i++) {
965 +                void *sig_stack = sig_stacks[i].ss_sp;
966 +                if (sig_stack)
967 +                        free(sig_stack);
968 +        }
969   #endif
970  
971          // Save NVRAM
# Line 1457 | Line 1494 | static void sigusr2_handler(int sig, sig
1494                  case MODE_NATIVE:
1495                          // 68k emulator inactive, in nanokernel?
1496                          if (r->gpr(1) != KernelDataAddr) {
1497 +
1498 +                                // Set extra stack for nested interrupts
1499 +                                sig_stack_acquire();
1500 +                                
1501                                  // Prepare for 68k interrupt level 1
1502                                  WriteMacInt16(ntohl(kernel_data->v[0x67c >> 2]), 1);
1503                                  WriteMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc, ReadMacInt32(ntohl(kernel_data->v[0x658 >> 2]) + 0xdc) | ntohl(kernel_data->v[0x674 >> 2]));
1504  
1505                                  // Execute nanokernel interrupt routine (this will activate the 68k emulator)
1506 <                                atomic_add((int32 *)XLM_IRQ_NEST, 1);
1506 >                                DisableInterrupt();
1507                                  if (ROMType == ROMTYPE_NEWWORLD)
1508                                          ppc_interrupt(ROM_BASE + 0x312b1c, KernelDataAddr);
1509                                  else
1510                                          ppc_interrupt(ROM_BASE + 0x312a3c, KernelDataAddr);
1511 +
1512 +                                // Reset normal signal stack
1513 +                                sig_stack_release();
1514                          }
1515                          break;
1516   #endif
# Line 1477 | Line 1521 | static void sigusr2_handler(int sig, sig
1521                          if ((ReadMacInt32(XLM_68K_R25) & 7) == 0) {
1522  
1523                                  // Set extra stack for SIGSEGV handler
1524 <                                struct sigaltstack new_stack;
1481 <                                new_stack.ss_sp = extra_stack;
1482 <                                new_stack.ss_flags = 0;
1483 <                                new_stack.ss_size = SIG_STACK_SIZE;
1484 <                                sigaltstack(&new_stack, NULL);
1524 >                                sig_stack_acquire();
1525   #if 1
1526                                  // Execute full 68k interrupt routine
1527                                  M68kRegisters r;
# Line 1508 | Line 1548 | static void sigusr2_handler(int sig, sig
1548                                  }
1549   #endif
1550                                  // Reset normal signal stack
1551 <                                new_stack.ss_sp = sig_stack;
1512 <                                new_stack.ss_flags = 0;
1513 <                                new_stack.ss_size = SIG_STACK_SIZE;
1514 <                                sigaltstack(&new_stack, NULL);
1551 >                                sig_stack_release();
1552                          }
1553                          break;
1554   #endif

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines