[project @ 2001-11-22 14:25:11 by simonmar]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
index 9bdc155..69de672 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: RtsStartup.c,v 1.47 2001/02/09 12:09:33 simonmar Exp $
+ * $Id: RtsStartup.c,v 1.56 2001/11/22 14:25:12 simonmar 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 */
-
-#ifdef GHCI
 #include "HsFFI.h"
 #include "Linker.h"
-#endif
 
 #if defined(RTS_GTK_FRONTPANEL)
 #include "FrontPanel.h"
 #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
 
 /*
@@ -55,10 +56,10 @@ 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);
+EXTFUN(__stginit_Prelude);
 static void initModules ( void (*)(void) );
 
 void
@@ -84,7 +85,7 @@ getProgArgv(int *argc, char **argv[])
 void
 startupHaskell(int argc, char *argv[], void (*init_root)(void))
 {
-    /* To avoid repeated initialisations of the RTS */
+   /* To avoid repeated initialisations of the RTS */
    if (rts_has_started_up)
      return;
    else
@@ -96,25 +97,19 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
     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. */
@@ -130,8 +125,9 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
 
 #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
@@ -152,11 +148,6 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
     /* initialize the storage manager */
     initStorage();
 
-    /* initialise the object linker, if necessary */
-#ifdef GHCI
-    initLinker();
-#endif
-
     /* initialise the stable pointer table */
     initStablePtrTable();
 
@@ -165,9 +156,7 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
 #endif
 
     /* run the per-module initialisation code */
-#if !defined(INTERPRETER)
     initModules(init_root);
-#endif
 
 #if defined(PROFILING) || defined(DEBUG)
     initProfiling2();
@@ -189,17 +178,9 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
     /* 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);
-#endif
-
 #ifdef RTS_GTK_FRONTPANEL
     if (RtsFlags.GcFlags.frontpanel) {
        initFrontPanel();
@@ -226,9 +207,9 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
       - 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,
@@ -238,32 +219,34 @@ startupHaskell(int argc, char *argv[], void (*init_root)(void))
 
 /* 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)(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(4);
+    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
@@ -277,7 +260,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
@@ -289,6 +277,26 @@ shutdownHaskell(void)
   /* start timing the shutdown */
   stat_startExit();
 
+#ifdef PROFILING
+  // @LDV profiling
+  // 
+  // Note: 
+  //   We do not need to perform a major garbage collection because all the
+  //   closures created since the last census will not affect the profiling
+  //   statistics anyhow.
+  // 
+  // Note: 
+  //   We ignore any object created afterwards. 
+  //   finalizeWeakPointersNow() may corrupt the heap (because it executes 
+  //   rts_evalIO(), which adds an initial evaluation stack again).
+  //   Thus, we call LdvCensusKillAll() here, and prohibit LDV profiling
+  //   afterwards. 
+  //   Acutally, it is pointless to call LdvCensusKillAll() any later because
+  //   no object created later will be taken into account for profiling.
+  if (RtsFlags.ProfFlags.doHeapProfile == HEAP_BY_LDV) 
+    LdvCensusKillAll();
+#endif
+
 #if !defined(GRAN)
   /* Finalize any remaining weak pointers */
   finalizeWeakPointersNow();
@@ -312,7 +320,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 */
@@ -329,12 +341,19 @@ shutdownHaskell(void)
     }
 #endif
 
+#if defined(PROFILING) 
+  report_ccs_profiling();
+#endif
+
 #if defined(PROFILING) || defined(DEBUG)
   endProfiling();
 #endif
 
-#if defined(PROFILING) 
-  report_ccs_profiling();
+#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)
@@ -342,20 +361,28 @@ shutdownHaskell(void)
 #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);
 }