1 /* -----------------------------------------------------------------------------
2 * $Id: RtsStartup.c,v 1.13 1999/05/21 14:28:32 sof 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"
36 struct RTS_FLAGS RtsFlags;
38 static int rts_has_started_up = 0;
41 startupHaskell(int argc, char *argv[])
45 /* To avoid repeated initialisations of the RTS */
46 if (rts_has_started_up)
52 int nPEs = 0; /* Number of PEs */
55 /* The very first thing we do is grab the start time...just in case we're
56 * collecting timing statistics.
62 *The parallel system needs to be initialised and synchronised before
65 if (*argv[0] == '-') { /* Look to see whether we're the Main Thread */
66 IAmMainThread = rtsTrue;
67 argv++; argc--; /* Strip off flag argument */
68 /* fprintf(stderr, "I am Main Thread\n"); */
71 * Grab the number of PEs out of the argument vector, and
72 * eliminate it from further argument processing.
77 initEachPEHook(); /* HWL: hook to be execed on each PE */
81 /* Set the RTS flags to default values. */
82 initRtsFlagsDefaults();
84 /* Call the user hook to reset defaults, if present */
87 /* Parse the flags, separating the RTS flags from the programs args */
88 setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
93 /* Initialise the parallel system -- before initHeap! */
95 /* And start GranSim profiling if required: omitted for now
96 *if (Rtsflags.ParFlags.granSimStats)
97 *init_gr_profiling(rts_argc, rts_argv, prog_argc, prog_argv);
101 /* initialize the storage manager */
104 /* initialise the stable pointer table */
105 initStablePtrTable();
107 #if defined(PROFILING) || defined(DEBUG)
111 /* Initialise the scheduler */
114 /* Initialise the stats department */
121 /* When the RTS and Prelude live in separate DLLs,
122 we need to patch up the char- and int-like tables
123 that the RTS keep after both DLLs have been loaded,
124 filling in the tables with references to where the
125 static info tables have been loaded inside the running
128 #ifdef ENABLE_WIN32_DLL_SUPPORT
130 (CHARLIKE_closure[i]).header.info = (const StgInfoTable*)&Czh_static_info;
133 (INTLIKE_closure[i]).header.info = (const StgInfoTable*)&Izh_static_info;
136 /* Record initialization times */
141 shutdownHaskell(void)
143 if (!rts_has_started_up)
146 /* Finalize any remaining weak pointers */
147 finalizeWeakPointersNow();
151 if (!RTSflags.GranFlags.granSimStats_suppressed)
155 /* clean up things from the storage manager's point of view */
158 #if defined(PROFILING) || defined(DEBUG)
162 #if defined(PROFILING)
163 report_ccs_profiling( );
166 #if defined(TICKY_TICKY)
167 if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
171 This fflush is important, because: if "main" just returns,
172 then we will end up in pre-supplied exit code that will close
173 streams and flush buffers. In particular we have seen: it
174 will close fd 0 (stdin), then flush fd 1 (stdout), then <who
177 But if you're playing with sockets, that "close fd 0" might
178 suggest to the daemon that all is over, only to be presented
179 with more stuff on "fd 1" at the flush.
181 The fflush avoids this sad possibility.
185 rts_has_started_up=0;
190 * called from STG-land to exit the program cleanly