[project @ 2001-12-10 17:59:54 by sof]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
index 48ae736..ce133dc 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: RtsStartup.c,v 1.42 2000/04/20 13:20:31 simonmar Exp $
+ * $Id: RtsStartup.c,v 1.59 2001/12/06 07:07:12 sof Exp $
  *
  * (c) The GHC Team, 1998-2000
  *
@@ -7,6 +7,7 @@
  *
  * ---------------------------------------------------------------------------*/
 
+#include "PosixSource.h"
 #include "Rts.h"
 #include "RtsAPI.h"
 #include "RtsUtils.h"
 #include "StgRun.h"
 #include "StgStartup.h"
 #include "Prelude.h"           /* fixupRTStoPreludeRefs */
+#include "HsFFI.h"
+#include "Linker.h"
+
+#if defined(RTS_GTK_FRONTPANEL)
+#include "FrontPanel.h"
+#endif
 
 #if defined(PROFILING) || defined(DEBUG)
 # include "Profiling.h"
 # include "ProfHeap.h"
+# include "RetainerProfile.h"
 #endif
 
 #if defined(GRAN)
-#include "GranSimRts.h"
-#include "ParallelRts.h"
+# include "GranSimRts.h"
+#endif
+
+#if defined(GRAN) || defined(PAR)
+# include "ParallelRts.h"
 #endif
 
 #if defined(PAR)
-#include "ParInit.h"
-#include "Parallel.h"
-#include "LLC.h"
+# include "Parallel.h"
+# include "LLC.h"
 #endif
 
 /*
@@ -46,11 +56,11 @@ struct RTS_FLAGS RtsFlags;
 
 static int rts_has_started_up = 0;
 #if defined(PAR)
-static ullong startTime = 0;
+ullong startTime = 0;
 #endif
 
-EXTFUN(__init_Prelude);
-static void initModules ( void * );
+EXTFUN(__stginit_Prelude);
+static void initModules ( void (*)(void) );
 
 void
 setProgArgv(int argc, char *argv[])
@@ -73,39 +83,38 @@ getProgArgv(int *argc, char **argv[])
 
 
 void
-startupHaskell(int argc, char *argv[], void *init_root)
+startupHaskell(int argc, char *argv[], void (*init_root)(void))
 {
-    /* To avoid repeated initialisations of the RTS */
-   if (rts_has_started_up)
-     return;
-   else
-     rts_has_started_up=1;
+   /* To avoid repeated initialisations of the RTS */
+  if (rts_has_started_up) {
+    /* RTS is up and running, so only run the per-module initialisation code */
+    if (init_root) {
+      initModules(init_root);
+    }
+    return;
+  } else {
+    rts_has_started_up=1;
+  }
 
     /* The very first thing we do is grab the start time...just in case we're
      * collecting timing statistics.
      */
-    start_time();
+    stat_startInit();
 
 #ifdef PAR
-/*
- * 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 */
-       // IF_PAR_DEBUG(verbose,
-                    fprintf(stderr, "[%x] I am Main Thread\n", mytid);
+    /*
+     * The parallel system needs to be initialised and synchronised before
+     * the program is run.  
+     */ 
+    startupParallelSystem(argv);
+     
+    if (*argv[0] == '-') { /* Strip off mainPE flag argument */
+      argv++; 
+      argc--;                  
     }
-    /* 
-     * Grab the number of PEs out of the argument vector, and
-     * eliminate it from further argument processing.
-     */
-    nPEs = atoi(argv[1]);
-    argv[1] = argv[0];
+
+    argv[1] = argv[0];   /* ignore the nPEs argument */
     argv++; argc--;
-    initEachPEHook();                  /* HWL: hook to be execed on each PE */
 #endif
 
     /* Set the RTS flags to default values. */
@@ -121,8 +130,9 @@ startupHaskell(int argc, char *argv[], void *init_root)
 
 #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
+    IF_PAR_DEBUG(verbose,
+                 fprintf(stderr, "==== Synchronising system (%d PEs)\n", nPEs));
+    synchroniseSystem();             // calls initParallelSystem etc
 #endif /* PAR */
 
     /* initialise scheduler data structures (needs to be done before
@@ -151,17 +161,14 @@ startupHaskell(int argc, char *argv[], void *init_root)
 #endif
 
     /* run the per-module initialisation code */
-#if !defined(INTERPRETER)
     initModules(init_root);
-#endif
 
 #if defined(PROFILING) || defined(DEBUG)
     initProfiling2();
 #endif
 
-    /* start the ticker */
-    install_vtalrm_handler();
-    initialize_virtual_timer(TICK_MILLISECS);
+    /* start the virtual timer 'subsystem'. */
+    startVirtTimer(TICK_MILLISECS);
 
     /* start our haskell execution tasks */
 #ifdef SMP
@@ -175,19 +182,17 @@ startupHaskell(int argc, char *argv[], void *init_root)
     /* Initialise the user signal handler set */
     initUserSignals();
     /* Set up handler to run on SIGINT, etc. */
-    init_default_handlers();
+    initDefaultHandlers();
 #endif
  
-#if !defined(INTERPRETER)
-    /* Initialise pointers from the RTS to the prelude.  
-       Only for compiled code -- the interpreter
-       will call this itself later, so don't do so now.
-    */
-    fixupRTStoPreludeRefs(NULL);
+#ifdef RTS_GTK_FRONTPANEL
+    if (RtsFlags.GcFlags.frontpanel) {
+       initFrontPanel();
+    }
 #endif
 
     /* Record initialization times */
-    end_init();
+    stat_endInit();
 }
 
 /* -----------------------------------------------------------------------------
@@ -206,9 +211,9 @@ startupHaskell(int argc, char *argv[], void *init_root)
       - 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_<module>" in each
-   module and calls the registration functions in each of the modules
-   it imports.  So, if we call "__init_PrelMain", each reachable module in the
+   The code generator inserts a small function "__stginit_<module>" in each
+   module and calls the registration functions in each of the modules it
+   imports.  So, if we call "__stginit_PrelMain", each reachable module in the
    program will be registered (because PrelMain.mainIO calls Main.main).
 
    The init* functions are compiled in the same way as STG code,
@@ -218,32 +223,34 @@ startupHaskell(int argc, char *argv[], void *init_root)
 
 /* The init functions use an explicit stack... 
  */
-#define INIT_STACK_SIZE  (BLOCK_SIZE * 4)
+#define INIT_STACK_BLOCKS  4
 F_ *init_stack = NULL;
 nat init_sp = 0;
 
-#ifndef INTERPRETER
 static void
-initModules ( void *init_root )
+initModules ( void (*init_root)(void) )
 {
+    bdescr *bd;
 #ifdef SMP
     Capability cap;
 #else
-#define cap MainRegTable
+#define cap MainCapability
 #endif
 
     init_sp = 0;
-    init_stack = (F_ *)allocate(INIT_STACK_SIZE / sizeof(W_));
+    bd = allocGroup(INIT_STACK_BLOCKS);
+    init_stack = (F_ *)bd->start;
     init_stack[init_sp++] = (F_)stg_init_ret;
-    init_stack[init_sp++] = (F_)__init_Prelude;
+    init_stack[init_sp++] = (F_)__stginit_Prelude;
     if (init_root != NULL) {
        init_stack[init_sp++] = (F_)init_root;
     }
     
-    cap.rSp = (P_)(init_stack + init_sp);
-    StgRun((StgFunPtr)stg_init, &cap);
+    cap.r.rSp = (P_)(init_stack + init_sp);
+    StgRun((StgFunPtr)stg_init, &cap.r);
+
+    freeGroup(bd);
 }
-#endif /* !INTERPRETER */
 
 /* -----------------------------------------------------------------------------
  * Shutting down the RTS - two ways of doing this, one which
@@ -257,7 +264,12 @@ shutdownHaskellAndExit(int n)
 {
   OnExitHook();
   shutdownHaskell();
+#if defined(PAR)
+  /* really exit (stg_exit() would call shutdownParallelSystem() again) */
+  exit(n);
+#else
   stg_exit(n);
+#endif
 }
 
 void
@@ -284,7 +296,7 @@ shutdownHaskell(void)
   exitScheduler();
 
   /* stop the ticker */
-  initialize_virtual_timer(0);
+  stopVirtTimer();
   
   /* reset the standard file descriptors to blocking mode */
   resetNonBlockingFd(0);
@@ -292,7 +304,11 @@ shutdownHaskell(void)
   resetNonBlockingFd(2);
 
 #if defined(PAR)
+  /* controlled exit; good thread! */
   shutdownParallelSystem(0);
+
+  /* global statistics in parallel system */
+  PAR_TICKY_PAR_END();
 #endif
 
   /* stop timing the shutdown, we're about to print stats */
@@ -303,33 +319,54 @@ shutdownHaskell(void)
    */
   exitStorage();
 
-#if defined(PROFILING) || defined(DEBUG)
-  endProfiling();
+#ifdef RTS_GTK_FRONTPANEL
+    if (RtsFlags.GcFlags.frontpanel) {
+       stopFrontPanel();
+    }
 #endif
 
 #if defined(PROFILING) 
   report_ccs_profiling();
 #endif
 
+#if defined(PROFILING) || defined(DEBUG)
+  endProfiling();
+#endif
+
+#ifdef PROFILING
+  // Originally, this was in report_ccs_profiling().  Now, retainer
+  // profiling might tack some extra stuff on to the end of this file
+  // during endProfiling().
+  fclose(prof_file);
+#endif
+
 #if defined(TICKY_TICKY)
   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
 #endif
 
   rts_has_started_up=0;
-
 }
 
 /* 
  * called from STG-land to exit the program
  */
 
+#ifdef PAR
+static int exit_started=rtsFalse;
+#endif
+
 void  
 stg_exit(I_ n)
-{
-#if 0 /* def PAR */
-  par_exit(n);
-#else
-  exit(n);
+{ 
+#ifdef PAR
+  /* HACK: avoid a loop when exiting due to a stupid error */
+  if (exit_started) 
+    return;
+  exit_started=rtsTrue;
+
+  IF_PAR_DEBUG(verbose, fprintf(stderr,"==-- stg_exit %d on [%x]...", n, mytid));
+  shutdownParallelSystem(n);
 #endif
+  exit(n);
 }