[project @ 2004-02-27 13:35:16 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
index 6826f5c..5255386 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: RtsStartup.c,v 1.69 2003/01/29 09:54:33 simonmar Exp $
+ * $Id: RtsStartup.c,v 1.79 2004/02/27 13:35:16 simonmar Exp $
  *
  * (c) The GHC Team, 1998-2002
  *
@@ -17,7 +17,7 @@
 #include "Schedule.h"   /* initScheduler */
 #include "Stats.h"      /* initStats */
 #include "Signals.h"
-#include "Itimer.h"
+#include "Timer.h"      /* startTimer, stopTimer */
 #include "Weak.h"
 #include "Ticky.h"
 #include "StgRun.h"
 # include "LLC.h"
 #endif
 
+#if defined(mingw32_TARGET_OS)
+#include "win32/AsyncIO.h"
+#endif
+
 #include <stdlib.h>
 
+#ifdef HAVE_LOCALE_H
+#include <locale.h>
+#endif
+
+#ifdef HAVE_TERMIOS_H
+#include <termios.h>
+#endif
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+
 // Flag Structure
 struct RTS_FLAGS RtsFlags;
 
 // Count of how many outstanding hs_init()s there have been.
 static int hs_init_count = 0;
 
+// Here we save the terminal settings on the standard file
+// descriptors, if we need to change them (eg. to support NoBuffering
+// input).
+static void *saved_termios[3] = {NULL,NULL,NULL};
+
+void*
+__hscore_get_saved_termios(int fd)
+{
+  return (0 <= fd && fd < (int)(sizeof(saved_termios) / sizeof(*saved_termios))) ?
+    saved_termios[fd] : NULL;
+}
+
+void
+__hscore_set_saved_termios(int fd, void* ts)
+{
+  if (0 <= fd && fd < (int)(sizeof(saved_termios) / sizeof(*saved_termios))) {
+    saved_termios[fd] = ts;
+  }
+}
+
 /* -----------------------------------------------------------------------------
    Starting up the RTS
    -------------------------------------------------------------------------- */
@@ -140,29 +175,33 @@ hs_init(int *argc, char **argv[])
     initProfiling1();
 #endif
 
-#if defined(PROFILING) || defined(DEBUG)
-    initProfiling2();
-#endif
-
     /* start the virtual timer 'subsystem'. */
-    startVirtTimer(TICK_MILLISECS);
+    startTimer(TICK_MILLISECS);
 
     /* Initialise the stats department */
     initStats();
 
-#if !defined(mingw32_TARGET_OS) && !defined(PAR)
+#if defined(RTS_USER_SIGNALS)
     /* Initialise the user signal handler set */
     initUserSignals();
     /* Set up handler to run on SIGINT, etc. */
     initDefaultHandlers();
 #endif
  
+#if defined(mingw32_TARGET_OS)
+    startupAsyncIO();
+#endif
+
 #ifdef RTS_GTK_FRONTPANEL
     if (RtsFlags.GcFlags.frontpanel) {
        initFrontPanel();
     }
 #endif
 
+#ifdef HAVE_LOCALE_H
+    setlocale(LC_ALL,"");
+#endif
+
     /* Record initialization times */
     stat_endInit();
 }
@@ -185,8 +224,8 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
 void
 getProgArgv(int *argc, char **argv[])
 {
-    *argc = prog_argc;
-    *argv = prog_argv;
+    if (argc) { *argc = prog_argc; }
+    if (argv) { *argv = prog_argv; }
 }
 
 void
@@ -258,6 +297,12 @@ hs_add_root(void (*init_root)(void))
     StgRun((StgFunPtr)stg_init, &cap.r);
 
     freeGroup(bd);
+
+#if defined(PROFILING) || defined(DEBUG)
+    // This must be done after module initialisation.
+    // ToDo: make this work in the presence of multiple hs_add_root()s.
+    initProfiling2();
+#endif
 }
 
 /* -----------------------------------------------------------------------------
@@ -279,14 +324,14 @@ hs_exit(void)
     /* start timing the shutdown */
     stat_startExit();
     
-    /* stop all running tasks */
-    exitScheduler();
-    
 #if !defined(GRAN)
     /* Finalize any remaining weak pointers */
     finalizeWeakPointersNow();
 #endif
     
+    /* stop all running tasks */
+    exitScheduler();
+    
 #if defined(GRAN)
     /* end_gr_simulation prints global stats if requested -- HWL */
     if (!RtsFlags.GranFlags.GranSimStats.Suppressed)
@@ -294,13 +339,34 @@ hs_exit(void)
 #endif
     
     /* stop the ticker */
-    stopVirtTimer();
+    stopTimer();
     
     /* reset the standard file descriptors to blocking mode */
     resetNonBlockingFd(0);
     resetNonBlockingFd(1);
     resetNonBlockingFd(2);
 
+#if HAVE_TERMIOS_H
+    // Reset the terminal settings on the standard file descriptors,
+    // if we changed them.  See System.Posix.Internals.tcSetAttr for
+    // more details, including the reason we termporarily disable
+    // SIGTTOU here.
+    { 
+       int fd;
+       sigset_t sigset, old_sigset;
+       sigemptyset(&sigset);
+       sigaddset(&sigset, SIGTTOU);
+       sigprocmask(SIG_BLOCK, &sigset, &old_sigset);
+       for (fd = 0; fd <= 2; fd++) {
+           struct termios* ts = (struct termios*)__hscore_get_saved_termios(fd);
+           if (ts != NULL) {
+               tcsetattr(fd,TCSANOW,ts);
+           }
+       }
+       sigprocmask(SIG_SETMASK, &old_sigset, NULL);
+    }
+#endif
+
 #if defined(PAR)
     /* controlled exit; good thread! */
     shutdownParallelSystem(0);
@@ -341,6 +407,10 @@ hs_exit(void)
 #if defined(TICKY_TICKY)
     if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
 #endif
+
+#if defined(mingw32_TARGET_OS)
+    shutdownAsyncIO();
+#endif
 }
 
 // Compatibility interfaces