[project @ 1996-07-25 20:43:49 by partain]
[ghc-hetmet.git] / ghc / runtime / main / Signals.lc
index af2738e..bfc10c3 100644 (file)
@@ -26,6 +26,10 @@ much pain.
 # define NON_POSIX_SOURCE
 #endif
 
+#if defined(freebsd_TARGET_OS)
+# define NON_POSIX_SOURCE
+#endif
+
 #if defined(osf1_TARGET_OS)
     /* The include files for OSF1 do not normally define SA_SIGINFO */
 # define _OSF_SOURCE 1
@@ -47,6 +51,11 @@ much pain.
 # include <signal.h>
 #endif
 
+#if defined(linux_TARGET_OS) || defined(linuxaout_TARGET_OS)
+    /* to look *inside* sigcontext... */
+# include <asm/signal.h>
+#endif
+
 #if defined(HAVE_SIGINFO_H)
     /* DEC OSF1 seems to need this explicitly.  Maybe others do as well? */
 # include <siginfo.h>
@@ -78,17 +87,25 @@ to set up the handler to expect a different collection of arguments.
 Fun, eh?
 
 \begin{code}
-# if defined(sunos4_TARGET_OS)
+# if defined(sunos4_TARGET_OS) || defined(freebsd_TARGET_OS) \
+  || defined(linux_TARGET_OS)  || defined(linuxaout_TARGET_OS)
 
 static void
-segv_handler(sig, code, scp, addr)
-  int sig;
-  int code; /* NB: all except first argument are "implementation defined" */
-  struct sigcontext *scp;
-  caddr_t addr;
+segv_handler(int sig,
+    /* NB: all except first argument are "implementation defined" */
+#  if defined(sunos4_TARGET_OS) || defined(freebsd_TARGET_OS)
+       int code, struct sigcontext *scp, caddr_t addr)
+#  else /* linux */
+       struct sigcontext_struct scp)
+#  endif /* linux */
 {
     extern void StackOverflow(STG_NO_ARGS) STG_NORETURN;
 
+#  if defined(linux_TARGET_OS)  || defined(linuxaout_TARGET_OS)
+    caddr_t addr = scp.cr2;
+    /* Magic info from Tommy Thorn! */
+#  endif
+
     if (addr >= (caddr_t) stks_space
       && addr < (caddr_t) (stks_space + RTSflags.GcFlags.stksSize))
        StackOverflow();
@@ -101,13 +118,20 @@ segv_handler(sig, code, scp, addr)
 int
 install_segv_handler(void)
 {
+#if freebsd_TARGET_OS
+    /* FreeBSD seems to generate SIGBUS for stack overflows */
+    if (signal(SIGBUS, segv_handler) == SIG_ERR)
+       return -1;
+    return ((int) signal(SIGSEGV, segv_handler));
+#else
     return ((int) signal(SIGSEGV, segv_handler) == SIG_ERR);
     /* I think the "== SIG_ERR" is saying "there was no
        handler for SIGSEGV before this one".  WDP 95/12
     */
+#endif
 }
 
-# else /* Not SunOS 4 */
+# else /* Not SunOS 4, FreeBSD, or Linux(a.out) */
 
 #  if defined(irix_TARGET_OS)
      /* certainly BOGUS (WDP 94/05) -- copied from /usr/include/sys/siginfo.h */
@@ -161,10 +185,12 @@ the non-POSIX signal under SunOS 4.1.X, we adopt the same approach
 here.
 
 \begin{code}
-#if (defined(PROFILING) || defined(CONCURRENT)) && !defined(GRAN)
+#if defined(PROFILING) || defined(CONCURRENT) /* && !defined(GRAN) */
 
 # ifdef CONCURRENT
 
+extern I_ delayTicks;
+
 #  ifdef PAR
 extern P_ CurrentTSO;
 #  endif
@@ -198,8 +224,27 @@ vtalrm_handler(int sig)
     }
 #  endif
 
-    if (WaitingThreadsHd != Nil_closure)
-       AwaitEvent(RTSflags.ConcFlags.ctxtSwitchTime);
+       /*
+        Handling a tick for threads blocked waiting for file
+        descriptor I/O or time.
+
+         This requires some care since virtual time alarm ticks
+        can occur when we are in the GC. If that is the case,
+        we just increment a delayed timer tick counter, but do
+         not check to see if any TSOs have been made runnable
+         as a result. (Do a bulk update of their status once
+        the GC has completed).
+
+        If the vtalrm does not occur within GC, we try to promote
+        any of the waiting threads to the runnable list (see awaitEvent)
+
+         4/96 SOF
+       */
+
+    if (delayTicks != 0) /* delayTicks>0 => don't handle timer expiry (in GC) */
+       delayTicks++;
+    else if (WaitingThreadsHd != Prelude_Z91Z93_closure)
+            AwaitEvent(RTSflags.ConcFlags.ctxtSwitchTime);
 
 #  ifdef PAR
     if (PendingSparksTl[REQUIRED_POOL] == PendingSparksLim[REQUIRED_POOL] ||
@@ -217,7 +262,7 @@ vtalrm_handler(int sig)
 
     if (CurrentTSO != NULL ||
 #  else
-    if (RunnableThreadsHd != Nil_closure ||
+    if (RunnableThreadsHd != Prelude_Z91Z93_closure ||
 #  endif
       PendingSparksHd[REQUIRED_POOL] < PendingSparksTl[REQUIRED_POOL] ||
       PendingSparksHd[ADVISORY_POOL] < PendingSparksTl[ADVISORY_POOL]) {
@@ -318,7 +363,7 @@ parallel world.  Sorry.
 
 \begin{code}
 
-#ifdef PAR
+#if defined(PAR) /* || defined(GRAN) */
 
 void
 blockUserSignals(void)
@@ -351,8 +396,8 @@ sig_install(sig, spi, mask)
 
 # include <setjmp.h>
 
-extern StgPtr deRefStablePointer PROTO((StgStablePtr));
-extern void freeStablePointer PROTO((I_));
+StgPtr deRefStablePointer PROTO((StgStablePtr));
+void freeStablePointer PROTO((I_));
 extern jmp_buf restart_main;
 
 static I_ *handlers = NULL; /* Dynamically grown array of signal handlers */
@@ -383,6 +428,8 @@ more_handlers(I_ sig)
     nHandlers = sig + 1;
 }
 
+I_ nocldstop = 0;
+
 # ifdef _POSIX_SOURCE
 
 static void
@@ -425,8 +472,6 @@ unblockUserSignals(void)
 }
 
 
-I_ nocldstop = 0;
-
 I_ 
 sig_install(sig, spi, mask)
   I_ sig;