1 /* -----------------------------------------------------------------------------
2 * $Id: RtsStartup.c,v 1.9 1999/03/09 14:27:06 sewardj Exp $
4 * (c) The GHC Team, 1998-1999
6 * Main function for a standalone Haskell program.
8 * ---------------------------------------------------------------------------*/
14 #include "Storage.h" /* initStorage, exitStorage */
15 #include "StablePriv.h" /* initStablePtrTable */
16 #include "Schedule.h" /* initScheduler */
17 #include "Stats.h" /* initStats */
21 #if defined(PROFILING)
24 # include "DebugProf.h"
34 #ifndef aix_TARGET_OS /* AIX gives link errors with this as a const (RO assembler section) */
37 StgClosure *PrelBase_Bool_closure_tbl[] = {
38 #ifndef HAVE_WIN32_DLL_SUPPORT
51 struct RTS_FLAGS RtsFlags;
53 extern void startupHaskell(int argc, char *argv[])
55 static int rts_has_started_up = 0;
58 /* To avoid repeated initialisations of the RTS */
59 if (rts_has_started_up)
65 int nPEs = 0; /* Number of PEs */
68 /* The very first thing we do is grab the start time...just in case we're
69 * collecting timing statistics.
75 *The parallel system needs to be initialised and synchronised before
78 if (*argv[0] == '-') { /* Look to see whether we're the Main Thread */
79 IAmMainThread = rtsTrue;
80 argv++; argc--; /* Strip off flag argument */
81 /* fprintf(stderr, "I am Main Thread\n"); */
84 * Grab the number of PEs out of the argument vector, and
85 * eliminate it from further argument processing.
90 initEachPEHook(); /* HWL: hook to be execed on each PE */
94 /* Set the RTS flags to default values. */
95 initRtsFlagsDefaults();
97 /* Call the user hook to reset defaults, if present */
100 /* Parse the flags, separating the RTS flags from the programs args */
101 setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
106 /* Initialise the parallel system -- before initHeap! */
107 initParallelSystem();
108 /* And start GranSim profiling if required: omitted for now
109 *if (Rtsflags.ParFlags.granSimStats)
110 *init_gr_profiling(rts_argc, rts_argv, prog_argc, prog_argv);
114 /* initialize the storage manager */
117 /* initialise the stable pointer table */
118 initStablePtrTable();
120 #if defined(PROFILING) || defined(DEBUG)
124 /* Initialise the scheduler */
127 /* Initialise the stats department */
134 /* When the RTS and Prelude live in separate DLLs,
135 we need to patch up the char- and int-like tables
136 that the RTS keep after both DLLs have been loaded,
137 filling in the tables with references to where the
138 static info tables have been loaded inside the running
141 Ditto for Bool closure tbl.
143 #ifdef HAVE_WIN32_DLL_SUPPORT
145 (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;
148 (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
150 PrelBase_Bool_closure_tbl[0] = (const StgClosure*)&False_closure;
151 PrelBase_Bool_closure_tbl[1] = (const StgClosure*)&True_closure;
153 /* Record initialization times */
158 shutdownHaskell(void)
160 /* Finalize any remaining weak pointers */
161 finalizeWeakPointersNow();
165 if (!RTSflags.GranFlags.granSimStats_suppressed)
169 /* clean up things from the storage manager's point of view */
172 #if defined(PROFILING) || defined(DEBUG)
176 #if defined(PROFILING)
177 report_ccs_profiling( );
180 #if defined(TICKY_TICKY)
181 if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
185 This fflush is important, because: if "main" just returns,
186 then we will end up in pre-supplied exit code that will close
187 streams and flush buffers. In particular we have seen: it
188 will close fd 0 (stdin), then flush fd 1 (stdout), then <who
191 But if you're playing with sockets, that "close fd 0" might
192 suggest to the daemon that all is over, only to be presented
193 with more stuff on "fd 1" at the flush.
195 The fflush avoids this sad possibility.
202 * called from STG-land to exit the program cleanly