home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / sml_nj / 93src.lha / src / runtime / signal.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-12  |  20.8 KB  |  718 lines

  1. /* signal.c
  2.  *
  3.  * COPYRIGHT (c) 1990 by AT&T Bell Laboratories.
  4.  *
  5.  * Machine independent signal support.
  6.  */
  7.  
  8. #ifdef THINK_C
  9. #include <signal.h>
  10. #include <setjmp.h>
  11. #else
  12. #include <sys/signal.h>
  13. #endif
  14. #include "ml_os.h"
  15. #include "ml_types.h"
  16. #include "request.h"
  17. #include "ml_signal.h"
  18. #include "prim.h"
  19. #include "ml_state.h"
  20. #include "fpregs.h"
  21. #include "sync.h"
  22. #ifdef AIX
  23. #include <fptrap.h>
  24. #include <fpxcp.h>
  25. #include <sys/except.h>
  26. #endif AIX
  27.  
  28. #include "cstack.h"
  29.  
  30. #ifdef HPPA
  31. # define sc_pc  sc_pcoq_head
  32. # define sc_npc sc_pcoq_tail
  33. #endif
  34.  
  35.  
  36. /* Purpose of the signal flags in the MLState_t vector:
  37.  *   inML          : This flag is set when we are executing ML code.  
  38.  *   handlerPending: This flag is set when a handler trap is pending,
  39.  *                   and cleared when handler trap is occurs.        
  40.  *   inSigHandler    : This flag is set when a handler trap occurs and
  41.  *                   is cleared when the ML handler returns.       
  42.  *   maskSignals   : When set, signals are masked.
  43.  *   ioWaitFlag    : This flag is set when we are waiting for a        
  44.  *               blocking I/O operation to be ready.
  45.  *   NumPendingSigs: This is the total number of signals pending.
  46.  *   SigTbl[]      : The number of pending signals of each type
  47.  *   SigCode       : The signal to be passed to ML
  48.  *   SigCount      : The number of pending signals of type sigCode
  49.  */
  50.  
  51. extern MLState_ptr find_self();
  52. extern void mp_shutdown();
  53. extern spin_lock_t siginfo_lock;
  54.  
  55. #ifdef THINK_C
  56. #include "MacOS.dep.h"
  57. static char    unix2ml[32]    /* map UNIX signal codes to ML signal codes */
  58.   = {
  59.     ML_NOSIG,      ML_SIGQUIT,    ML_NOSIG,     ML_NOSIG,        /* 0-3 */    /* 1=SIGABRT=>QUIT? */
  60.     ML_SIGINT,      ML_NOSIG,    ML_SIGTERM,   ML_NOSIG,        /* 4-7 */
  61.     ML_SIGHUP,      ML_SIGALRM,    ML_SIGUSR1,   ML_SIGUSR2,    /* 8-11 */
  62.     ML_SIGQUIT,      ML_SIGTSTP,    ML_SIGCONT,   ML_SIGURG,    /* 12-15 */
  63.     ML_SIGCHLD,      ML_SIGIO,    ML_SIGWINCH,  ML_NOSIG,        /* 16-19 */
  64.     ML_NOSIG,      ML_NOSIG,    ML_NOSIG,     ML_NOSIG,        /* 20-23 */
  65.     ML_NOSIG,      ML_NOSIG,    ML_NOSIG,     ML_NOSIG,        /* 24-27 */
  66.     ML_NOSIG,      ML_NOSIG,    ML_NOSIG,     ML_NOSIG        /* 28-31 */
  67.   };
  68. #else
  69. static char    unix2ml[]    /* map UNIX signal codes to ML signal codes */
  70.   = {
  71.     ML_NOSIG,      ML_SIGHUP,    ML_SIGINT,    ML_SIGQUIT,    /* 0-3 */
  72.     ML_NOSIG,      ML_NOSIG,    ML_NOSIG,     ML_NOSIG,        /* 4-7 */
  73.     ML_NOSIG,      ML_NOSIG,    ML_NOSIG,     ML_NOSIG,        /* 8-11 */
  74.     ML_NOSIG,      ML_NOSIG,    ML_SIGALRM,   ML_SIGTERM,    /* 12-15 */
  75. #ifdef HPUX
  76.     ML_SIGUSR1,      ML_SIGUSR2,    ML_SIGCHLD,   ML_NOSIG,        /* 16-19 */
  77.     ML_NOSIG,      ML_NOSIG,    ML_SIGIO,     ML_SIGWINCH,    /* 20-23 */
  78.     ML_NOSIG,      ML_SIGTSTP,    ML_SIGCONT,   ML_NOSIG,        /* 24-27 */
  79.     ML_NOSIG,      ML_SIGURG,    ML_NOSIG,     ML_NOSIG,        /* 28-31 */
  80. #else /* !HPUX */
  81. #if defined(RISCos) || defined(SGI)
  82.     ML_SIGUSR1,      ML_SIGUSR2,    ML_SIGCHLD,   ML_NOSIG,        /* 16-19 */
  83.     ML_NOSIG,      ML_SIGTSTP,    ML_NOSIG,     ML_SIGIO,        /* 20-23 */
  84.     ML_SIGURG,      ML_SIGWINCH,    ML_SIGVTALRM, ML_SIGPROF,    /* 24-27 */
  85.     ML_SIGCONT,      ML_NOSIG,    ML_NOSIG,     ML_NOSIG,        /* 28-31 */
  86. #else /* !HPUX && !SGI */
  87. #ifdef AUX
  88.     ML_SIGUSR1,      ML_SIGUSR2,    ML_SIGCHLD,   ML_NOSIG,        /* 16-19 */
  89.     ML_SIGTSTP,      ML_NOSIG,    ML_NOSIG,     ML_NOSIG,        /* 20-23 */
  90.     ML_NOSIG,      ML_NOSIG,    ML_SIGVTALRM, ML_SIGPROF,    /* 24-27 */
  91.     ML_SIGWINCH,  ML_SIGCONT,    ML_SIGURG,    ML_SIGIO        /* 28-31 */
  92. #else /* !HPUX && !SGI && !AUX */
  93. #ifdef AIX
  94.     ML_SIGURG,      ML_NOSIG,    ML_SIGTSTP,   ML_SIGCONT,    /* 16-19 */
  95.     ML_SIGCHLD,   ML_NOSIG,     ML_NOSIG,     ML_SIGIO,        /* 20-23 */
  96.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,        /* 24-27 */
  97.     ML_SIGWINCH,  ML_NOSIG,     ML_SIGUSR1,   ML_SIGUSR2,    /* 28-31 */
  98.     ML_SIGPROF,   ML_NOSIG,     ML_SIGVTALRM, ML_NOSIG,         /* 32-35 */
  99.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,         /* 36-39 */
  100.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,         /* 40-43 */
  101.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,         /* 44-47 */
  102.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,         /* 48-51 */
  103.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,         /* 52-55 */
  104.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,         /* 56-59 */
  105.     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,     ML_NOSIG,         /* 60-63 */
  106. #else /* !HPUX && !SGI && !AUX && !AIX */
  107.     ML_SIGURG,      ML_NOSIG,    ML_SIGTSTP,   ML_SIGCONT,    /* 16-19 */
  108.     ML_SIGCHLD,      ML_NOSIG,    ML_NOSIG,     ML_SIGIO,        /* 20-23 */
  109.     ML_NOSIG,      ML_NOSIG,    ML_SIGVTALRM, ML_SIGPROF,    /* 24-27 */
  110.     ML_SIGWINCH,  ML_NOSIG,    ML_SIGUSR1,   ML_SIGUSR2    /* 28-31 */
  111. #endif
  112. #endif
  113. #endif
  114. #endif
  115.   };
  116. #endif
  117.  
  118. static struct siginfo_t {    /* Info about the ML signals */
  119.     char        unix_code;        /* the unix signal code of this signal */
  120.     char        state;        /* the state of this signal. */
  121.     char            default_action; /* what to do when disabled */
  122. } siginfo[NUM_ML_SIGS] =
  123. {
  124.     { SIGHUP,        ML_SIG_DISABLED, DFL_TERM_NO_CORE },
  125.     { SIGINT,        ML_SIG_DISABLED, DFL_TERM_NO_CORE },
  126.     { SIGQUIT,        ML_SIG_DISABLED, DFL_NO_HANDLER },
  127.     { SIGALRM,        ML_SIG_DISABLED, DFL_TERM_NO_CORE },
  128.     { SIGTERM,        ML_SIG_DISABLED, DFL_TERM_NO_CORE },
  129.     { SIGURG,        ML_SIG_DISABLED, DFL_IGNORE },
  130. #ifdef HPUX
  131.     { SIGCHLD,        ML_SIG_DISABLED, DFL_NO_HANDLER },
  132. #else
  133.     { SIGCHLD,        ML_SIG_DISABLED, DFL_IGNORE },
  134. #endif
  135.     { SIGIO,        ML_SIG_DISABLED, DFL_IGNORE },
  136.     { SIGWINCH,        ML_SIG_DISABLED, DFL_IGNORE },
  137.     { SIGUSR1,        ML_SIG_DISABLED, DFL_TERM_NO_CORE },
  138.     { SIGUSR2,        ML_SIG_DISABLED, DFL_TERM_NO_CORE },
  139.     { SIGTSTP,        ML_SIG_DISABLED, DFL_NO_HANDLER },
  140.     { SIGCONT,        ML_SIG_DISABLED, DFL_NO_HANDLER },
  141.     { SIG_NOT_UNIX, ML_SIG_DISABLED, DFL_IGNORE },    
  142.     { SIGVTALRM,    ML_SIG_DISABLED, DFL_TERM_NO_CORE },    
  143.     { SIGPROF,      ML_SIG_DISABLED, DFL_NO_HANDLER },    
  144.     /* ML_SIGGC (garbage collection) */
  145. };
  146.  
  147.  
  148. /* sig_setup:
  149.  * This (machine independent) function is called by the (machine dependent) function
  150.  * ghandle to set things up for handling a signal in ML.  Since this is called by
  151.  * ghandle, it is atomic w.r.t. signals.
  152.  */
  153. void sig_setup (msp)
  154.     MLState_ptr msp;
  155. {
  156.     register int    nextSig, oldmask;
  157.  
  158. #ifndef THINK_C
  159.     oldmask  = sigblock(0xffffffff);
  160. #endif
  161.     nextSig = msp->SigCode;
  162.  
  163.   /* determine which signal to handle */
  164.     do {
  165.     if ((nextSig += 1) == NUM_ML_SIGS)
  166.         nextSig = 0;
  167.     } while (msp->SigTbl[nextSig] == 0);
  168.  
  169.   /* record the signal and count */
  170.     msp->SigCode     = nextSig;
  171.     msp->SigCount     = msp->SigTbl[nextSig];
  172.     msp->NumPendingSigs  -= msp->SigCount;
  173.     msp->SigTbl[nextSig] = 0;
  174.  
  175.     msp->handlerPending  = 0;
  176.     msp->inSigHandler    = 1;
  177.  
  178. #ifndef THINK_C
  179.     sigsetmask(oldmask);
  180. #endif
  181.  
  182. } /* end of sig_setup */
  183.  
  184.  
  185. /* FORCE_TRAP:
  186.  * Set the ML heap limit to 0 so that next limit check will trap back to C.
  187.  * Called from within signal handlers.
  188.  * Implementation is machine-dependent:
  189.  * the heap limit usually lives in a register, which may or may not
  190.  * be accessible through scp; on some machines, it lives in the ML
  191.  * stack frame or in a global.
  192.  * Where possible, we adjust the limit directly from within the handler.
  193.  * Otherwise, we set the handler's return pc to point at a routine
  194.  * adjust_limit (see *.prim.s) that adjusts the limit upon return
  195.  * from the signal handler.  In this case, we store the real return pc
  196.  * in global saved_pc; this solution is inadequate for multiprocessors. */
  197. #ifdef THINK_C
  198. #define FORCE_TRAP(msp,scp) (scp)->sc_regs[5] = 0
  199. #else
  200. #ifdef MIPS
  201. #define FORCE_TRAP(msp,scp) (scp)->sc_regs[19] = 0 
  202. #else
  203. #ifdef I386
  204. #define FORCE_TRAP(msp,scp) (msp)->MLframe[3] = 0
  205. #else
  206. #ifdef HPPA
  207. #define FORCE_TRAP(msp,scp) (scp)->sc_gr19 = 0
  208. #else
  209. #ifdef C
  210. #define FORCE_TRAP(msp,scp) plimit = 0
  211. #else
  212. #ifdef AIX
  213. #define FORCE_TRAP(msp,scp) (scp)->sc_jmpbuf.jmp_context.gpr[15] = 0
  214. #else
  215. int saved_pc;              /* saved_pc to restore in adjust_limit */
  216. # ifdef SPARC
  217. #define FORCE_TRAP(msp,scp) {                                            \
  218.      register int pc = (scp)->sc_pc;                                     \
  219.      (scp)->sc_pc = (int)adjust_limit;                                   \
  220.      if (pc+4 != (scp)->sc_npc) {                                        \
  221.     /* the pc is pointing to a delay slot, so back-up to the branch. \
  222.      * Note: this relies on the assumption that the branch doesn't   \
  223.      * have a side-effect that interferes with the delay slot. */    \
  224.     pc -= 4;                                                         \
  225.      };                                                                  \
  226.      (scp)->sc_npc = ((int)adjust_limit)+4;                              \
  227.      saved_pc = pc;                                                      \
  228.      }
  229. # else
  230. #define FORCE_TRAP(msp,scp) {                 \
  231.      register int pc = (scp)->sc_pc;          \
  232.      (scp)->sc_pc = (int)adjust_limit;        \
  233.      saved_pc = pc;                           \
  234.     }
  235. #endif
  236. #endif
  237. #endif
  238. #endif
  239. #endif
  240. #endif
  241. #endif
  242.  
  243. /* sig_handler:
  244.  * The C signal handler for signals that are to be passed to the ML handler.
  245.  */
  246. SIGH_RET_TYPE sig_handler (sig, code, scp)
  247.     int            sig, code;
  248.     struct sigcontext *scp;
  249. {
  250.     extern int        adjust_limit[];
  251.     MLState_ptr     msp = find_self();
  252.     int             ml_sig;
  253.  
  254.     ml_sig = unix2ml[sig];
  255.     if ((siginfo[ml_sig].state) == ML_SIG_DISABLED) {
  256.     if (siginfo[ml_sig].default_action == DFL_TERM_NO_CORE) {
  257.         mp_shutdown (msp, 1);
  258.     }
  259.     }
  260.     else {
  261.     /* record the signal */
  262.       msp->NumPendingSigs++;
  263.       msp->SigTbl[ml_sig]++;
  264.  
  265.       if (!msp->maskSignals) {
  266.     if (msp->ioWaitFlag) {
  267.       /* We were waiting for a blocking I/O operation when the signal occurred,
  268.        * so longjmp out of the operation (see io_wait() in "cfuns.c"). */
  269. #ifdef THINK_C
  270.          longjmp (msp->SysCallEnv, 1);
  271. #else
  272.         _longjmp (msp->SysCallEnv, 1);
  273. #endif
  274.        }
  275.     else if (msp->inML && (!msp->handlerPending) && 
  276.          (! msp->inSigHandler)) {
  277.         msp->handlerPending    = 1;
  278.         FORCE_TRAP(msp,scp);
  279.       }
  280.       }
  281.     }
  282. } /* end of sig_handler */
  283.  
  284.  
  285. #if (MAX_PROCS > 1)
  286. /* The signal handler for GC synchronization signals (SIGUSR1). */
  287. SIGH_RET_TYPE gc_sync_handler (sig, code, scp)
  288.      int  sig, code;
  289.      struct sigcontext *scp;
  290. {
  291.   extern int adjust_limit[];
  292.   extern int should_exit;
  293.   MLState_ptr     msp = find_self();
  294.  
  295. #ifdef MP_DEBUG
  296.   pchatting("[gsynch signal received]\n");
  297. #endif MP_DEBUG
  298.   if (should_exit) 
  299.     mp_shutdown (msp,0);
  300.  
  301.   if (msp->ioWaitFlag) {
  302. #ifdef THINK_C
  303.      longjmp (msp->SysCallEnv, 1);
  304. #else
  305.     _longjmp (msp->SysCallEnv, 1);
  306. #endif
  307.   }
  308.   else if (msp->inML) {
  309.     FORCE_TRAP(msp,scp);
  310.   }
  311. }
  312. #endif /* (MAX_PROCS > 1) */
  313.  
  314.  
  315. /* handlesys:
  316.  * The handler for SIGSYS.
  317.  */
  318. SIGH_RET_TYPE handlesys ()
  319. {
  320.   /* Long jump to back to ml_syscall. */
  321. #ifdef THINK_C
  322.      longjmp ((find_self())->SysCallEnv, 1);
  323. #else
  324.     _longjmp ((find_self())->SysCallEnv, 1);
  325. #endif
  326. }
  327.  
  328.  
  329. /* handleprof:
  330.  * The handler for profile signals.
  331.  */
  332. SIGH_RET_TYPE handleprof ()
  333. {
  334.    extern ML_val_t current0[], *times0[];
  335.    int curr = INT_MLtoC(current0[1]);
  336.    ML_val_t *times_array = times0[1];
  337.    times_array[curr] = INT_incr(times_array[curr],1);
  338.  /* possibility of a slight inaccuracy here:
  339.     if current==2 (meaning "Garbage Collection"), then 
  340.     it could be that times0[1] is in the middle of being forwarded,
  341.     in which case the wrong version of the times array might be incremented.
  342.     However, I don't think this can lead to any bug other than a missed
  343.     tick attributable to g.c. */
  344. }
  345.  
  346.  
  347. /* gcsignal:
  348.  * Record a garbage collection signal (if enabled).  Return true, if a signal
  349.  * was recorded.
  350.  */
  351. int gcsignal (msp)
  352.     MLState_ptr msp;
  353. {
  354.     if (siginfo[ML_SIGGC].state == ML_SIG_ENABLED) {
  355.     msp->NumPendingSigs++;
  356.     msp->SigTbl[ML_SIGGC]++;
  357.     return 1;
  358.     }
  359.     else
  360.     return 0;
  361.  
  362. } /* end of gcsignal */
  363.  
  364.  
  365.  
  366. #define SIGMASKALL        0xffffffff    /* mask all signals */
  367.  
  368. /* turn_off_signals: tell the OS to ignore all signals.  This is used
  369.  * while a proc is sleeping so that it doesn't react to signals that
  370.  * are sent while it is sleeping.
  371.  */
  372. void turn_off_signals(msp)
  373.      MLState_ptr msp;
  374. {
  375.   int ml_sig, sig;
  376.  
  377.   for (ml_sig = 0; ml_sig < NUM_ML_SIGS; ml_sig++) {
  378.     sig = siginfo[ml_sig].unix_code;
  379.     if (sig != SIGUSR1)
  380.       SETSIG(sig,SIG_IGN,SIGMASKALL);
  381.   }
  382. }
  383.  
  384. extern int request_fault[];
  385.  
  386. static SIGH_RET_TYPE trap_handler(sig,code,scp)
  387.      int sig,code;
  388.      struct sigcontext *scp;
  389. {
  390.     MLState_ptr MLState = find_self();
  391.  
  392. #ifdef BSD386
  393.     /* Due to an OS bug, SIGBUS is generated by an INTO instruction */
  394.     if (sig == SIGBUS) {
  395.        sig = SIGFPE; 
  396.        code = FPE_INTOVF_TRAP;
  397.        /* PC no longer needs to be adjusted by +1? */
  398.     }
  399. #endif
  400.  
  401.     if (!MLState->inML) 
  402.     die ("bogus signal not in ML: (%d, %#x)\n", sig, code);
  403.     
  404.  
  405. #ifdef MIPS
  406.     make_exn_code (MLState, scp, sig, code? code : scp->sc_fpc_csr);
  407. #else
  408.     make_exn_code (MLState, scp, sig, code);
  409. #endif MIPS
  410.  
  411.  
  412. #ifdef C
  413.     request = REQ_FAULT
  414.     saveregs (MLState);
  415. #else
  416. #ifdef AIX
  417.     {
  418.     /*
  419.     ** On the RS6000 the exception bits are sticky.
  420.     ** We  need to reset them before exit from here.
  421.     */
  422.     struct mstsave     * scj = &(scp->sc_jmpbuf.jmp_context);
  423.     fp_ctx_t    flt_context;
  424.     
  425.     scj->xer           &= 0x3fffffff;
  426.         fp_sh_trap_info(scp,&flt_context);
  427.     fp_sh_set_stat(scp,(flt_context.fpscr & ~flt_context.trap));
  428.  
  429.         scp->sc_jmpbuf.jmp_context.iar     = (int)request_fault;
  430.     return;
  431.     }
  432. #else   
  433.     scp->sc_pc = (int)request_fault;
  434. #ifdef SPARC
  435.     scp->sc_npc = scp->sc_pc + 4;
  436. #else
  437. #if defined(HPPA) && defined(HPUX)
  438.     scp->sc_pcoq_tail = scp->sc_pc + 4;
  439.     scp->sc_pcsq_tail = scp->sc_pcsq_head = pointer2space(request_fault);
  440.     if (sig == SIGFPE && code == 0xd) {
  441.        /* this is a bit weird.  integer division is done by a function call
  442.       to C code (millicode really), which requires saving some
  443.       registers.  the /0 trap happens in that millicode. but
  444.       request_fault assumes the registers have ML values.  so we have
  445.       to restore what was saved before doing the division. */
  446.  
  447.        char *sp = scp->sc_gr30;
  448.        scp->sc_gr8 = * (int *) (sp + callersave_offset(8));
  449.        scp->sc_gr9 = * (int *) (sp + callersave_offset(9));
  450.        scp->sc_gr10 = * (int *) (sp + callersave_offset(10));
  451.        scp->sc_gr11 = * (int *) (sp + callersave_offset(11));
  452.        scp->sc_gr29 = * (int *) (sp + othersave_offset(0));
  453.        scp->sc_gr31 = * (int *) (sp + othersave_offset(1));
  454.        scp->sc_gr26 = * (int *) (sp + othersave_offset(2));
  455.        scp->sc_gr24 = * (int *) (sp + othersave_offset(4));
  456.        scp->sc_gr23 = * (int *) (sp + othersave_offset(5));
  457.        
  458.     }
  459.     scp->sc_sl.sl_ss.ss_frstat = 0xe;
  460. #endif
  461. #endif
  462. #endif
  463. #endif
  464.  
  465. } /* trap_handler */
  466.  
  467. /* setup_signals:  setup the C signal handlers for ML catch-able signals.
  468.  * Also, if this is the first time a proc has called it, then we need to
  469.  * install any C signal handlers needed by the runtime.  Note that on
  470.  * MP systems, SIGUSR1 is unavailable for use.
  471.  */
  472. void setup_signals (msp, first_time)
  473.      MLState_ptr msp;
  474.      int         first_time;
  475. {
  476.     int            ml_sig, sig;
  477.  
  478.   /* set up the ML signals according to their state */
  479.     for (ml_sig = 0;  ml_sig < NUM_ML_SIGS;  ml_sig++) {
  480.     sig = siginfo[ml_sig].unix_code;
  481. #if (MAX_PROCS > 1)
  482.     if (sig != SIG_NOT_UNIX && sig != SIGUSR1)
  483. #else
  484.     if (sig != SIG_NOT_UNIX)
  485. #endif
  486.         switch (siginfo[ml_sig].default_action) {
  487.             case DFL_NO_HANDLER:
  488.             if (siginfo[ml_sig].state == ML_SIG_ENABLED) {
  489.           SETSIG (sig, sig_handler, SIGMASKALL);
  490.         } else {
  491.           SETSIG (sig, SIG_DFL, SIGMASKALL);
  492.         }
  493.         break;
  494.           case DFL_TERM_NO_CORE: /* fall through */
  495.           case DFL_IGNORE:
  496.         SETSIG (sig, sig_handler, SIGMASKALL);
  497.         break;
  498.           }
  499.     }
  500.  
  501.     if (first_time) {
  502.       SETSIG (SIGPIPE, SIG_IGN, 0);  /* will force an EPIPE error instead */
  503.       SETSIG (SIGSYS, handlesys, SIGMASKALL);
  504.       SETSIG (SIGVTALRM, handleprof, SIGMASKALL);
  505. #if (MAX_PROCS > 1)
  506.       SETSIG(SIGUSR1, gc_sync_handler, SIGMASKALL);
  507. #endif
  508.  
  509.     /* setup the machine dependent signals. */
  510.       SETSIG(SIGFPE, trap_handler, SIGMASKALL);
  511.  
  512. #ifdef SPARC
  513. #ifdef MACH
  514.   /* MACH on sun-4s use SIGILL for some causes of Overflow */
  515.     SETSIG (SIGILL, trap_handler, SIGMASKALL);
  516. #endif
  517.     set_fsr (0x0d000000); /* enable FP exceptions NV, OF, & DZ; disable UF */
  518. #endif
  519.  
  520. #ifdef MIPS
  521.     SETSIG(SIGTRAP, trap_handler, SIGMASKALL);
  522.     set_fsr();  /* enable floating-point exceptions */
  523. #endif
  524.  
  525. #ifdef BSD386
  526.     /* Due to OS bug, SIGBUS is generated by an INTO instruction. */
  527.     SETSIG(SIGBUS, trap_handler, SIGMASKALL);
  528. #endif   
  529.  
  530. #ifdef AUX
  531.   /* A/UX uses SIGILL for integer overflow traps */
  532.     SETSIG (SIGILL, trap_handler, SIGMASKALL);
  533. #endif
  534.  
  535. #if defined(M68) || defined(I386)
  536. #ifdef THINK_C
  537.     SETSIG (SIGTRAP, trap_handler, SIGMASKALL);
  538.     init_TRAPS();
  539.     signal(SIGFPE,  e_raise);
  540.     SETSIG (SIGFPE, trap_handler, SIGMASKALL);
  541.     signal(SIGABRT, e_raise);
  542.     signal(SIGINT,  e_raise);
  543.     signal(SIGTERM, e_restart_handler);
  544. #endif
  545.     fpenable();
  546. #endif
  547.  
  548. #ifdef AIX
  549.     SETSIG(SIGTRAP,trap_handler,SIGMASKALL);
  550.     fp_clr_flag(FP_ALL_XCP);    /* clear all floating exception bits */
  551.     fp_enable_all();        /* enable all FE exceptions */
  552.     fp_disable(TRP_INEXACT);    /* see me if you want this -lg */
  553. #endif AIX
  554.     }
  555.  
  556. #ifdef HPPA
  557.     set_fsr();
  558. #endif 
  559.  
  560. } /* end of setup_signals */
  561.  
  562.  
  563. /* enable_sig:
  564.  */
  565. void enable_sig (ml_sig, enable)
  566.     int            ml_sig, enable;
  567. {
  568.     int            sig;
  569.  
  570.     while (!(try_spin_lock(siginfo_lock))) /* spin */;
  571.  
  572.     siginfo[ml_sig].state = (enable ? ML_SIG_ENABLED : ML_SIG_DISABLED);
  573.     spin_unlock(siginfo_lock);
  574.     if (((sig = siginfo[ml_sig].unix_code) != SIG_NOT_UNIX) &&
  575.     (siginfo[ml_sig].default_action == DFL_NO_HANDLER)) {
  576.     if (enable) {
  577.         SETSIG (sig, sig_handler, SIGMASKALL);
  578.     } else {
  579.         SETSIG (sig, SIG_IGN, SIGMASKALL);
  580.     }
  581.     }
  582.  
  583. } /* end of enable_sig */
  584.  
  585.  
  586. /* make_ml_sigh_arg:
  587.  * Build the argument record for the ML signal handler.  It has the type
  588.  *
  589.  *   val sigHandler : (int * int * unit cont) -> 'a
  590.  *
  591.  * The first arg is the signal code, the second is the signal count and the
  592.  * third is the resumption continuation.  The ML signal handler should never
  593.  * return.
  594.  *
  595.  * Layout of the resumption continuation:
  596.  *
  597.  *                  resumption continuation
  598.  *                            |
  599.  *                            v
  600.  *   +------------------+----+-+-+-+-+-+~+---------~
  601.  *   | STRING floatregs |desc|1|2|3|4| |B| live regs
  602.  *   +------------------+----+-+-+-+-+|+~+---------~
  603.  *           ^                        |
  604.  *           |________________________|
  605.  *
  606.  * At least 4K avail. heap assumed.
  607.  */
  608. ML_val_t make_ml_sigh_arg (msp)
  609.      MLState_ptr msp;
  610. {
  611.     ML_val_t    resume_c, arg;
  612.     int        i, n, mask;
  613.     ML_val_t     fpregs;
  614.  
  615.   /* save floating point registers. */
  616. #if (NSAVED_FPREGS > 0)
  617. #ifdef I386    /* Need to save entire FP state. */
  618.     ML_alloc_write (msp, 0, MAKE_DESC(FP_STATE_SIZE, TAG_string));
  619.     msp->ml_allocptr += sizeof(long);
  620.     fpregs = PTR_CtoML(msp->ml_allocptr);
  621.     savefpregs (msp->ml_allocptr);
  622.     msp->ml_allocptr += FP_STATE_SIZE;
  623. #else
  624.     savefpregs (msp);
  625.     fpregs = PTR_CtoML(msp->ml_allocptr + sizeof(long));
  626.     msp->ml_allocptr += (NSAVED_FPREGS*2 + 1) * sizeof(long);
  627. #endif I386
  628. #else
  629.     fpregs = ML_unit;
  630. #endif
  631.  
  632.   /* allocate the closure for resume */
  633.     ML_alloc_write (msp, 1, PTR_CtoML(sigh_resume));
  634.     ML_alloc_write (msp, 2, INT_CtoML(msp->mask));
  635.     ML_alloc_write (msp, 3, msp->ml_pc);
  636.     ML_alloc_write (msp, 4, msp->ml_exncont);
  637.     ML_alloc_write (msp, 5, fpregs);
  638.     n = 6; 
  639.     /*
  640.      * note that varptr and (if defined) icount are 
  641.      * shared between mainline ML code and exn handler, so
  642.      * are not saved/restored here.
  643.      */
  644.  
  645. #if defined(BASE_INDX)
  646.     ML_alloc_write (msp, n, msp->ml_baseptr);
  647.     n++;
  648. #endif
  649. #if defined(C)
  650.       mask = Cmask;
  651.       ML_alloc_write (msp, n, INT_CtoML(Cmask));
  652.       n++;
  653. #else /* !defined(C) */
  654.     mask = msp->mask;
  655. #endif
  656.     for (i = 0;  mask != 0;  i++) {
  657.     if (mask & 0x1) {
  658.         ML_alloc_write (msp, n, msp->ml_roots[ArgRegMap[i]]);
  659.         n++;
  660.     }
  661.     mask >>= 1;
  662.     }
  663.     ML_alloc_write (msp, 0, MAKE_DESC(n-1, TAG_record));
  664.     resume_c = ML_alloc(msp, n-1);
  665.  
  666.   /* allocate the ML signal handler's argument record */
  667.     REC_ALLOC3(msp, arg,
  668.     INT_CtoML(msp->SigCode), INT_CtoML(msp->SigCount), resume_c);
  669.  
  670.     return arg;
  671.  
  672. } /* end of make_ml_sigh_arg. */
  673.  
  674.  
  675. /* load_resume_state:
  676.  * Load the ML state vector with the state preserved in a resumption continuation
  677.  * built by make_ml_sigh_arg.
  678.  */
  679. void load_resume_state (msp)
  680.      MLState_ptr msp;
  681. {
  682.  
  683. #if (CALLEESAVE > 0)
  684.     register ML_val_t *p = (ML_val_t *)(PTR_MLtoC(msp->ml_closure));
  685. #else
  686.     register ML_val_t *p = (ML_val_t *)(PTR_MLtoC(msp->ml_cont));
  687. #endif
  688.     register int    i, n, mask;
  689.  
  690.     mask = msp->mask = INT_MLtoC(p[1]);
  691.     msp->ml_pc = p[2];
  692.     msp->ml_exncont = p[3];
  693. #if (NSAVED_FPREGS > 0)
  694.     restorefpregs(p[4]);
  695. #endif
  696.     n = 5;
  697. #if defined(BASE_INDX)
  698.     msp->ml_baseptr = p[n];
  699.     n++;
  700. #endif
  701. #if defined(C)
  702.   /** NOTE: this probably doesn't work anymore!!! **/
  703.     mask = ((unsigned int) p[n]) >> 1;
  704.     n++;
  705. #endif
  706.     for (i = 0;  mask != 0;  i++) {
  707.     if (mask & 0x1) {
  708.         msp->ml_roots[ArgRegMap[i]] = p[n++];
  709.     }
  710.     mask >>= 1;
  711.     }
  712.  
  713. } /* end of load_resume_state. */
  714.  
  715.  
  716.  
  717.  
  718.