[project @ 2000-03-14 14:34:47 by sewardj]
[ghc-hetmet.git] / ghc / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  * $Id: RtsStartup.c,v 1.34 2000/03/14 14:34:47 sewardj Exp $
3  *
4  * (c) The GHC Team, 1998-2000
5  *
6  * Main function for a standalone Haskell program.
7  *
8  * ---------------------------------------------------------------------------*/
9
10 #include "Rts.h"
11 #include "RtsAPI.h"
12 #include "RtsUtils.h"
13 #include "RtsFlags.h"  
14 #include "Storage.h"    /* initStorage, exitStorage */
15 #include "StablePriv.h" /* initStablePtrTable */
16 #include "Schedule.h"   /* initScheduler */
17 #include "Stats.h"      /* initStats */
18 #include "Signals.h"
19 #include "Itimer.h"
20 #include "Weak.h"
21 #include "Ticky.h"
22 #include "StgRun.h"
23 #include "StgStartup.h"
24 #include "Prelude.h"            /* fixupRTStoPreludeRefs */
25
26 #if defined(PROFILING) || defined(DEBUG)
27 # include "ProfRts.h"
28 # include "ProfHeap.h"
29 #endif
30
31 #if defined(GRAN)
32 #include "GranSimRts.h"
33 #include "ParallelRts.h"
34 #endif
35
36 #if defined(PAR)
37 #include "ParInit.h"
38 #include "Parallel.h"
39 #include "LLC.h"
40 #endif
41
42 /*
43  * Flag Structure
44  */
45 struct RTS_FLAGS RtsFlags;
46
47 static int rts_has_started_up = 0;
48 #if defined(PAR)
49 static ullong startTime = 0;
50 #endif
51
52 static void initModules ( void );
53
54 void
55 startupHaskell(int argc, char *argv[])
56 {
57     /* To avoid repeated initialisations of the RTS */
58    if (rts_has_started_up)
59      return;
60    else
61      rts_has_started_up=1;
62
63     /* The very first thing we do is grab the start time...just in case we're
64      * collecting timing statistics.
65      */
66     start_time();
67
68 #ifdef PAR
69 /*
70  * The parallel system needs to be initialised and synchronised before
71  * the program is run.  
72  */
73     fprintf(stderr, "startupHaskell: argv[0]=%s\n", argv[0]);
74     if (*argv[0] == '-') {     /* Look to see whether we're the Main Thread */
75         IAmMainThread = rtsTrue;
76         argv++; argc--;                 /* Strip off flag argument */
77         // IF_PAR_DEBUG(verbose,
78                      fprintf(stderr, "[%x] I am Main Thread\n", mytid);
79     }
80     /* 
81      * Grab the number of PEs out of the argument vector, and
82      * eliminate it from further argument processing.
83      */
84     nPEs = atoi(argv[1]);
85     argv[1] = argv[0];
86     argv++; argc--;
87     initEachPEHook();                  /* HWL: hook to be execed on each PE */
88 #endif
89
90     /* Set the RTS flags to default values. */
91     initRtsFlagsDefaults();
92
93     /* Call the user hook to reset defaults, if present */
94     defaultsHook();
95
96     /* Parse the flags, separating the RTS flags from the programs args */
97     setupRtsFlags(&argc, argv, &rts_argc, rts_argv);
98     prog_argc = argc;
99     prog_argv = argv;
100
101 #if defined(PAR)
102     /* NB: this really must be done after processing the RTS flags */
103     fprintf(stderr, "Synchronising system (%d PEs)\n", nPEs);
104     SynchroniseSystem();             // calls initParallelSystem etc
105 #endif  /* PAR */
106
107     /* initialise scheduler data structures (needs to be done before
108      * initStorage()).
109      */
110     initScheduler();
111
112 #if defined(GRAN)
113     /* And start GranSim profiling if required: */
114     if (RtsFlags.GranFlags.GranSimStats.Full)
115       init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
116 #elif defined(PAR)
117     /* And start GUM profiling if required: */
118     if (RtsFlags.ParFlags.ParStats.Full)
119       init_gr_simulation(rts_argc, rts_argv, prog_argc, prog_argv);
120 #endif  /* PAR || GRAN */
121
122     /* initialize the storage manager */
123     initStorage();
124
125     /* initialise the stable pointer table */
126     initStablePtrTable();
127
128 #if defined(PROFILING) || defined(DEBUG)
129     initProfiling1();
130 #endif
131
132     /* run the per-module initialisation code */
133 #if !defined(INTERPRETER)
134     initModules();
135 #endif
136
137 #if defined(PROFILING) || defined(DEBUG)
138     initProfiling2();
139 #endif
140
141     /* start the ticker */
142     install_vtalrm_handler();
143     initialize_virtual_timer(TICK_MILLISECS);
144
145     /* start our haskell execution tasks */
146 #ifdef SMP
147     startTasks();
148 #endif
149
150     /* Initialise the stats department */
151     initStats();
152
153 #if !defined(mingw32_TARGET_OS) && !defined(PAR)
154     /* Initialise the user signal handler set */
155     initUserSignals();
156     /* Set up handler to run on SIGINT, etc. */
157     init_default_handlers();
158 #endif
159  
160 #if !defined(INTERPRETER)
161     /* Initialise pointers from the RTS to the prelude.  
162        Only for compiled code -- the interpreter
163        will call this itself later, so don't do so now.
164     */
165     fixupRTStoPreludeRefs(NULL);
166 #endif
167
168     /* Record initialization times */
169     end_init();
170 }
171
172 /* -----------------------------------------------------------------------------
173    Per-module initialisation
174
175    This process traverses all the compiled modules in the program
176    starting with "Main", and performing per-module initialisation for
177    each one.
178
179    So far, two things happen at initialisation time:
180
181       - we register stable names for each foreign-exported function
182         in that module.  This prevents foreign-exported entities, and
183         things they depend on, from being garbage collected.
184
185       - we supply a unique integer to each statically declared cost
186         centre and cost centre stack in the program.
187
188    The code generator inserts a small function "__init_<module>" in each
189    module and calls the registration functions in each of the modules
190    it imports.  So, if we call "__init_Main", each reachable module in the
191    program will be registered.
192
193    The init* functions are compiled in the same way as STG code,
194    i.e. without normal C call/return conventions.  Hence we must use
195    StgRun to call this stuff.
196    -------------------------------------------------------------------------- */
197
198 #ifndef INTERPRETER
199
200 /* The init functions use an explicit stack... 
201  */
202 #define INIT_STACK_SIZE  (BLOCK_SIZE * 4)
203 F_ *init_stack;
204
205 static void
206 initModules ( void )
207 {
208   /* this storage will be reclaimed by the garbage collector,
209    * as a large block.
210    */
211   init_stack = (F_ *)allocate(INIT_STACK_SIZE / sizeof(W_));
212
213   StgRun((StgFunPtr)stg_init, NULL/* no reg table */);
214 }
215
216 #endif /* !INTERPRETER */
217
218 /* -----------------------------------------------------------------------------
219  * Shutting down the RTS - two ways of doing this, one which
220  * calls exit(), one that doesn't.
221  *
222  * (shutdownHaskellAndExit() is called by System.exitWith).
223  * -----------------------------------------------------------------------------
224  */
225 void
226 shutdownHaskellAndExit(int n)
227 {
228   OnExitHook();
229   shutdownHaskell();
230   stg_exit(n);
231 }
232
233 void
234 shutdownHaskell(void)
235 {
236   if (!rts_has_started_up)
237      return;
238
239   /* start timing the shutdown */
240   stat_startExit();
241
242 #if !defined(GRAN)
243   /* Finalize any remaining weak pointers */
244   finalizeWeakPointersNow();
245 #endif
246
247 #if defined(GRAN)
248   /* end_gr_simulation prints global stats if requested -- HWL */
249   if (!RtsFlags.GranFlags.GranSimStats.Suppressed)
250     end_gr_simulation();
251 #endif
252
253   /* stop all running tasks */
254   exitScheduler();
255
256   /* stop the ticker */
257   initialize_virtual_timer(0);
258   
259   /* reset the standard file descriptors to blocking mode */
260   resetNonBlockingFd(0);
261   resetNonBlockingFd(1);
262   resetNonBlockingFd(2);
263
264   /* stop timing the shutdown, we're about to print stats */
265   stat_endExit();
266
267   /* clean up things from the storage manager's point of view.
268    * also outputs the stats (+RTS -s) info.
269    */
270   exitStorage();
271
272 #if defined(PROFILING) || defined(DEBUG)
273   endProfiling();
274 #endif
275
276 #if defined(PROFILING) 
277   report_ccs_profiling();
278 #endif
279
280 #if defined(TICKY_TICKY)
281   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
282 #endif
283
284   rts_has_started_up=0;
285
286 #if defined(PAR)
287   shutdownParallelSystem(0);
288 #endif
289
290 }
291
292 /* 
293  * called from STG-land to exit the program
294  */
295
296 void  
297 stg_exit(I_ n)
298 {
299 #if 0 /* def PAR */
300   par_exit(n);
301 #else
302   exit(n);
303 #endif
304 }
305