[project @ 2000-03-08 17:48:24 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
index 1c50c08..6de0350 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: RtsStartup.c,v 1.16 1999/07/03 18:39:40 sof Exp $
+ * $Id: RtsStartup.c,v 1.31 2000/03/08 17:48:24 simonmar Exp $
  *
  * (c) The GHC Team, 1998-1999
  *
 #include "StablePriv.h" /* initStablePtrTable */
 #include "Schedule.h"   /* initScheduler */
 #include "Stats.h"      /* initStats */
+#include "Signals.h"
+#include "Itimer.h"
 #include "Weak.h"
 #include "Ticky.h"
+#include "StgRun.h"
+#include "StgStartup.h"
 
-#if defined(PROFILING)
+#if defined(PROFILING) || defined(DEBUG)
 # include "ProfRts.h"
-#elif defined(DEBUG)
-# include "DebugProf.h"
+# include "ProfHeap.h"
 #endif
 
-#ifdef PAR
+#if defined(GRAN)
+#include "GranSimRts.h"
+#include "ParallelRts.h"
+#endif
+
+#if defined(PAR)
 #include "ParInit.h"
 #include "Parallel.h"
 #include "LLC.h"
 struct RTS_FLAGS RtsFlags;
 
 static int rts_has_started_up = 0;
+#if defined(PAR)
+static ullong startTime = 0;
+#endif
+
+static void initModules ( void );
 
 void
 startupHaskell(int argc, char *argv[])
@@ -50,10 +63,6 @@ startupHaskell(int argc, char *argv[])
    else
      rts_has_started_up=1;
 
-#if defined(PAR)
-    int nPEs = 0;                  /* Number of PEs */
-#endif
-
     /* The very first thing we do is grab the start time...just in case we're
      * collecting timing statistics.
      */
@@ -61,13 +70,15 @@ startupHaskell(int argc, char *argv[])
 
 #ifdef PAR
 /*
- *The parallel system needs to be initialised and synchronised before
- *the program is run.  
+ * The parallel system needs to be initialised and synchronised before
+ * the program is run.  
  */
+    fprintf(stderr, "startupHaskell: argv[0]=%s\n", argv[0]);
     if (*argv[0] == '-') {     /* Look to see whether we're the Main Thread */
        IAmMainThread = rtsTrue;
         argv++; argc--;                        /* Strip off flag argument */
-/*     fprintf(stderr, "I am Main Thread\n"); */
+       // IF_PAR_DEBUG(verbose,
+                    fprintf(stderr, "[%x] I am Main Thread\n", mytid);
     }
     /* 
      * Grab the number of PEs out of the argument vector, and
@@ -77,7 +88,6 @@ startupHaskell(int argc, char *argv[])
     argv[1] = argv[0];
     argv++; argc--;
     initEachPEHook();                  /* HWL: hook to be execed on each PE */
-    SynchroniseSystem();
 #endif
 
     /* Set the RTS flags to default values. */
@@ -91,15 +101,27 @@ startupHaskell(int argc, char *argv[])
     prog_argc = argc;
     prog_argv = argv;
 
-#ifdef PAR
-   /* Initialise the parallel system -- before initHeap! */
-    initParallelSystem();
-   /* And start GranSim profiling if required: omitted for now
-    *if (Rtsflags.ParFlags.granSimStats)
-    *init_gr_profiling(rts_argc, rts_argv, prog_argc, prog_argv);
-    */
+#if defined(PAR)
+    /* NB: this really must be done after processing the RTS flags */
+    fprintf(stderr, "Synchronising system (%d PEs)\n", nPEs);
+    SynchroniseSystem();             // calls initParallelSystem etc
 #endif /* PAR */
 
+    /* initialise scheduler data structures (needs to be done before
+     * initStorage()).
+     */
+    initScheduler();
+
+#if defined(GRAN)
+    /* And start GranSim profiling if required: */
+    if (RtsFlags.GranFlags.GranSimStats.Full)
+      init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
+#elif defined(PAR)
+    /* And start GUM profiling if required: */
+    if (RtsFlags.ParFlags.ParStats.Full)
+      init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
+#endif /* PAR || GRAN */
+
     /* initialize the storage manager */
     initStorage();
 
@@ -107,17 +129,33 @@ startupHaskell(int argc, char *argv[])
     initStablePtrTable();
 
 #if defined(PROFILING) || defined(DEBUG)
-    initProfiling();
+    initProfiling1();
 #endif
 
-    /* Initialise the scheduler */
-    initScheduler();
+    /* run the per-module initialisation code */
+    initModules();
+
+#if defined(PROFILING) || defined(DEBUG)
+    initProfiling2();
+#endif
+
+    /* start the ticker */
+    install_vtalrm_handler();
+    initialize_virtual_timer(TICK_MILLISECS);
+
+    /* start our haskell execution tasks */
+#ifdef SMP
+    startTasks();
+#endif
 
     /* Initialise the stats department */
     initStats();
 
-#if 0
+#if !defined(mingw32_TARGET_OS) && !defined(PAR)
+    /* Initialise the user signal handler set */
     initUserSignals();
+    /* Set up handler to run on SIGINT, etc. */
+    init_default_handlers();
 #endif
  
     /* When the RTS and Prelude live in separate DLLs,
@@ -139,15 +177,59 @@ startupHaskell(int argc, char *argv[])
     end_init();
 }
 
-/*
+/* -----------------------------------------------------------------------------
+   Per-module initialisation
+
+   This process traverses all the compiled modules in the program
+   starting with "Main", and performing per-module initialisation for
+   each one.
+
+   So far, two things happen at initialisation time:
+
+      - we register stable names for each foreign-exported function
+        in that module.  This prevents foreign-exported entities, and
+       things they depend on, from being garbage collected.
+
+      - we supply a unique integer to each statically declared cost
+        centre and cost centre stack in the program.
+
+   The code generator inserts a small function "__init_<moddule>" in each
+   module and calls the registration functions in each of the modules
+   it imports.  So, if we call "__init_Main", each reachable module in the
+   program will be registered.
+
+   The init* functions are compiled in the same way as STG code,
+   i.e. without normal C call/return conventions.  Hence we must use
+   StgRun to call this stuff.
+   -------------------------------------------------------------------------- */
+
+/* The init functions use an explicit stack... 
+ */
+#define INIT_STACK_SIZE  (BLOCK_SIZE * 4)
+F_ *init_stack;
+
+static void
+initModules ( void )
+{
+  /* this storage will be reclaimed by the garbage collector,
+   * as a large block.
+   */
+  init_stack = (F_ *)allocate(INIT_STACK_SIZE / sizeof(W_));
+
+  StgRun((StgFunPtr)stg_init, NULL/* no reg table */);
+}
+
+/* -----------------------------------------------------------------------------
  * Shutting down the RTS - two ways of doing this, one which
  * calls exit(), one that doesn't.
  *
  * (shutdownHaskellAndExit() is called by System.exitWith).
+ * -----------------------------------------------------------------------------
  */
 void
 shutdownHaskellAndExit(int n)
 {
+  OnExitHook();
   shutdownHaskell();
   stg_exit(n);
 }
@@ -158,16 +240,37 @@ shutdownHaskell(void)
   if (!rts_has_started_up)
      return;
 
+  /* start timing the shutdown */
+  stat_startExit();
+
+#if !defined(GRAN)
   /* Finalize any remaining weak pointers */
   finalizeWeakPointersNow();
+#endif
 
 #if defined(GRAN)
-  #error FixMe.
-  if (!RTSflags.GranFlags.granSimStats_suppressed)
+  /* end_gr_simulation prints global stats if requested -- HWL */
+  if (!RtsFlags.GranFlags.GranSimStats.Suppressed)
     end_gr_simulation();
 #endif
 
-  /* clean up things from the storage manager's point of view */
+  /* stop all running tasks */
+  exitScheduler();
+
+  /* stop the ticker */
+  initialize_virtual_timer(0);
+  
+  /* reset the standard file descriptors to blocking mode */
+  resetNonBlockingFd(0);
+  resetNonBlockingFd(1);
+  resetNonBlockingFd(2);
+
+  /* stop timing the shutdown, we're about to print stats */
+  stat_endExit();
+
+  /* clean up things from the storage manager's point of view.
+   * also outputs the stats (+RTS -s) info.
+   */
   exitStorage();
 
 #if defined(PROFILING) || defined(DEBUG)
@@ -175,7 +278,7 @@ shutdownHaskell(void)
 #endif
 
 #if defined(PROFILING) 
-  report_ccs_profiling( );
+  report_ccs_profiling();
 #endif
 
 #if defined(TICKY_TICKY)
@@ -183,20 +286,24 @@ shutdownHaskell(void)
 #endif
 
   rts_has_started_up=0;
-}
 
+#if defined(PAR)
+  shutdownParallelSystem(0);
+#endif
+
+}
 
 /* 
- * called from STG-land to exit the program cleanly 
+ * called from STG-land to exit the program
  */
 
 void  
 stg_exit(I_ n)
 {
-#ifdef PAR
+#if 0 /* def PAR */
   par_exit(n);
 #else
-  OnExitHook();
   exit(n);
 #endif
 }
+