Add capability sets to the tracing/events system
[ghc-hetmet.git] / rts / RtsStartup.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2002
4  *
5  * Main function for a standalone Haskell program.
6  *
7  * ---------------------------------------------------------------------------*/
8
9 // PAPI uses caddr_t, which is not POSIX
10 #ifndef USE_PAPI
11 #include "PosixSource.h"
12 #endif
13
14 #include "Rts.h"
15 #include "RtsAPI.h"
16 #include "HsFFI.h"
17
18 #include "sm/Storage.h"
19 #include "RtsFlags.h"
20 #include "RtsUtils.h"
21 #include "Prelude.h"
22 #include "Schedule.h"   /* initScheduler */
23 #include "Stats.h"      /* initStats */
24 #include "STM.h"        /* initSTM */
25 #include "RtsSignals.h"
26 #include "Weak.h"
27 #include "Ticky.h"
28 #include "StgRun.h"
29 #include "Prelude.h"            /* fixupRTStoPreludeRefs */
30 #include "ThreadLabels.h"
31 #include "sm/BlockAlloc.h"
32 #include "Trace.h"
33 #include "Stable.h"
34 #include "Hash.h"
35 #include "Profiling.h"
36 #include "Timer.h"
37 #include "Globals.h"
38 void exitLinker( void );        // there is no Linker.h file to include
39
40 #if defined(RTS_GTK_FRONTPANEL)
41 #include "FrontPanel.h"
42 #endif
43
44 #if defined(PROFILING)
45 # include "ProfHeap.h"
46 # include "RetainerProfile.h"
47 #endif
48
49 #if defined(mingw32_HOST_OS) && !defined(THREADED_RTS)
50 #include "win32/AsyncIO.h"
51 #endif
52
53 #if !defined(mingw32_HOST_OS)
54 #include "posix/TTY.h"
55 #include "posix/FileLock.h"
56 #endif
57
58 #ifdef HAVE_UNISTD_H
59 #include <unistd.h>
60 #endif
61 #ifdef HAVE_LOCALE_H
62 #include <locale.h>
63 #endif
64
65 #if USE_PAPI
66 #include "Papi.h"
67 #endif
68
69 // Count of how many outstanding hs_init()s there have been.
70 static int hs_init_count = 0;
71
72 /* -----------------------------------------------------------------------------
73    Initialise floating point unit on x86 (currently disabled; See Note
74    [x86 Floating point precision] in compiler/nativeGen/X86/Instr.hs)
75    -------------------------------------------------------------------------- */
76
77 #define X86_INIT_FPU 0
78
79 #if X86_INIT_FPU
80 static void
81 x86_init_fpu ( void )
82 {
83   __volatile unsigned short int fpu_cw;
84
85   // Grab the control word
86   __asm __volatile ("fnstcw %0" : "=m" (fpu_cw));
87
88 #if 0
89   printf("fpu_cw: %x\n", fpu_cw);
90 #endif
91
92   // Set bits 8-9 to 10 (64-bit precision).
93   fpu_cw = (fpu_cw & 0xfcff) | 0x0200;
94
95   // Store the new control word back
96   __asm __volatile ("fldcw %0" : : "m" (fpu_cw));
97 }
98 #endif
99
100 /* -----------------------------------------------------------------------------
101    Starting up the RTS
102    -------------------------------------------------------------------------- */
103
104 void
105 hs_init(int *argc, char **argv[])
106 {
107     hs_init_count++;
108     if (hs_init_count > 1) {
109         // second and subsequent inits are ignored
110         return;
111     }
112
113     setlocale(LC_CTYPE,"");
114
115     /* Initialise the stats department, phase 0 */
116     initStats0();
117
118     /* Next we do is grab the start time...just in case we're
119      * collecting timing statistics.
120      */
121     stat_startInit();
122
123     /* Set the RTS flags to default values. */
124
125     initRtsFlagsDefaults();
126
127     /* Call the user hook to reset defaults, if present */
128     defaultsHook();
129
130     /* Parse the flags, separating the RTS flags from the programs args */
131     if (argc != NULL && argv != NULL) {
132         setFullProgArgv(*argc,*argv);
133         setupRtsFlags(argc, *argv);
134     }
135
136     /* Initialise the stats department, phase 1 */
137     initStats1();
138
139 #ifdef USE_PAPI
140     papi_init();
141 #endif
142
143     /* initTracing must be after setupRtsFlags() */
144 #ifdef TRACING
145     initTracing();
146 #endif
147     /* Trace the startup event
148      */
149     traceEventStartup();
150
151     /* initialise scheduler data structures (needs to be done before
152      * initStorage()).
153      */
154     initScheduler();
155
156     /* initialize the storage manager */
157     initStorage();
158
159     /* initialise the stable pointer table */
160     initStablePtrTable();
161
162     /* Add some GC roots for things in the base package that the RTS
163      * knows about.  We don't know whether these turn out to be CAFs
164      * or refer to CAFs, but we have to assume that they might.
165      */
166     getStablePtr((StgPtr)runIO_closure);
167     getStablePtr((StgPtr)runNonIO_closure);
168
169     getStablePtr((StgPtr)runFinalizerBatch_closure);
170
171     getStablePtr((StgPtr)stackOverflow_closure);
172     getStablePtr((StgPtr)heapOverflow_closure);
173     getStablePtr((StgPtr)unpackCString_closure);
174     getStablePtr((StgPtr)blockedIndefinitelyOnMVar_closure);
175     getStablePtr((StgPtr)nonTermination_closure);
176     getStablePtr((StgPtr)blockedIndefinitelyOnSTM_closure);
177     getStablePtr((StgPtr)nestedAtomically_closure);
178
179     getStablePtr((StgPtr)runSparks_closure);
180     getStablePtr((StgPtr)ensureIOManagerIsRunning_closure);
181 #ifndef mingw32_HOST_OS
182     getStablePtr((StgPtr)runHandlers_closure);
183 #endif
184
185     /* initialise the shared Typeable store */
186     initGlobalStore();
187
188     /* initialise file locking, if necessary */
189 #if !defined(mingw32_HOST_OS)    
190     initFileLocking();
191 #endif
192
193 #if defined(DEBUG)
194     /* initialise thread label table (tso->char*) */
195     initThreadLabelTable();
196 #endif
197
198     initProfiling1();
199
200     /* start the virtual timer 'subsystem'. */
201     initTimer();
202     startTimer();
203
204 #if defined(RTS_USER_SIGNALS)
205     if (RtsFlags.MiscFlags.install_signal_handlers) {
206         /* Initialise the user signal handler set */
207         initUserSignals();
208         /* Set up handler to run on SIGINT, etc. */
209         initDefaultHandlers();
210     }
211 #endif
212  
213 #if defined(mingw32_HOST_OS) && !defined(THREADED_RTS)
214     startupAsyncIO();
215 #endif
216
217 #ifdef RTS_GTK_FRONTPANEL
218     if (RtsFlags.GcFlags.frontpanel) {
219         initFrontPanel();
220     }
221 #endif
222
223 #if X86_INIT_FPU
224     x86_init_fpu();
225 #endif
226
227     startupHpc();
228
229     // This must be done after module initialisation.
230     // ToDo: make this work in the presence of multiple hs_add_root()s.
231     initProfiling2();
232
233     // ditto.
234 #if defined(THREADED_RTS)
235     ioManagerStart();
236 #endif
237
238     /* Record initialization times */
239     stat_endInit();
240 }
241
242 // Compatibility interface
243 void
244 startupHaskell(int argc, char *argv[], void (*init_root)(void) STG_UNUSED)
245 {
246     hs_init(&argc, &argv);
247 }
248
249
250 /* -----------------------------------------------------------------------------
251    hs_add_root: backwards compatibility.  (see #3252)
252    -------------------------------------------------------------------------- */
253
254 void
255 hs_add_root(void (*init_root)(void) STG_UNUSED)
256 {
257     /* nothing */
258 }
259
260 /* ----------------------------------------------------------------------------
261  * Shutting down the RTS
262  *
263  * The wait_foreign parameter means:
264  *       True  ==> wait for any threads doing foreign calls now.
265  *       False ==> threads doing foreign calls may return in the
266  *                 future, but will immediately block on a mutex.
267  *                 (capability->lock).
268  * 
269  * If this RTS is a DLL that we're about to unload, then you want
270  * safe=True, otherwise the thread might return to code that has been
271  * unloaded.  If this is a standalone program that is about to exit,
272  * then you can get away with safe=False, which is better because we
273  * won't hang on exit if there is a blocked foreign call outstanding.
274  *
275  ------------------------------------------------------------------------- */
276
277 static void
278 hs_exit_(rtsBool wait_foreign)
279 {
280     if (hs_init_count <= 0) {
281         errorBelch("warning: too many hs_exit()s");
282         return;
283     }
284     hs_init_count--;
285     if (hs_init_count > 0) {
286         // ignore until it's the last one
287         return;
288     }
289
290     /* start timing the shutdown */
291     stat_startExit();
292     
293     OnExitHook();
294
295     // sanity check
296 #if defined(DEBUG)
297     checkFPUStack();
298 #endif
299
300 #if defined(THREADED_RTS)
301     ioManagerDie();
302 #endif
303
304     /* stop all running tasks */
305     exitScheduler(wait_foreign);
306
307     /* run C finalizers for all active weak pointers */
308     runAllCFinalizers(weak_ptr_list);
309     
310 #if defined(RTS_USER_SIGNALS)
311     if (RtsFlags.MiscFlags.install_signal_handlers) {
312         freeSignalHandlers();
313     }
314 #endif
315
316     /* stop the ticker */
317     stopTimer();
318     exitTimer(wait_foreign);
319
320     // set the terminal settings back to what they were
321 #if !defined(mingw32_HOST_OS)    
322     resetTerminalSettings();
323 #endif
324
325     // uninstall signal handlers
326     resetDefaultHandlers();
327
328     /* stop timing the shutdown, we're about to print stats */
329     stat_endExit();
330     
331     /* shutdown the hpc support (if needed) */
332     exitHpc();
333
334     // clean up things from the storage manager's point of view.
335     // also outputs the stats (+RTS -s) info.
336     exitStorage();
337     
338     /* free the tasks */
339     freeScheduler();
340
341     /* free shared Typeable store */
342     exitGlobalStore();
343
344     /* free linker data */
345     exitLinker();
346
347     /* free file locking tables, if necessary */
348 #if !defined(mingw32_HOST_OS)    
349     freeFileLocking();
350 #endif
351
352     /* free the stable pointer table */
353     exitStablePtrTable();
354
355 #if defined(DEBUG)
356     /* free the thread label table */
357     freeThreadLabelTable();
358 #endif
359
360 #ifdef RTS_GTK_FRONTPANEL
361     if (RtsFlags.GcFlags.frontpanel) {
362         stopFrontPanel();
363     }
364 #endif
365
366 #if defined(PROFILING) 
367     reportCCSProfiling();
368 #endif
369
370     endProfiling();
371     freeProfiling();
372
373 #ifdef PROFILING
374     // Originally, this was in report_ccs_profiling().  Now, retainer
375     // profiling might tack some extra stuff on to the end of this file
376     // during endProfiling().
377     if (prof_file != NULL) fclose(prof_file);
378 #endif
379
380 #ifdef TRACING
381     endTracing();
382     freeTracing();
383 #endif
384
385 #if defined(TICKY_TICKY)
386     if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
387 #endif
388
389 #if defined(mingw32_HOST_OS) && !defined(THREADED_RTS)
390     shutdownAsyncIO(wait_foreign);
391 #endif
392
393     /* free hash table storage */
394     exitHashTable();
395
396     // Finally, free all our storage.  However, we only free the heap
397     // memory if we have waited for foreign calls to complete;
398     // otherwise a foreign call in progress may still be referencing
399     // heap memory (e.g. by being passed a ByteArray#).
400     freeStorage(wait_foreign);
401
402     // Free the various argvs
403     freeRtsArgs();
404 }
405
406 // The real hs_exit():
407 void
408 hs_exit(void)
409 {
410     hs_exit_(rtsTrue);
411     // be safe; this might be a DLL
412 }
413
414 // Compatibility interfaces
415 void
416 shutdownHaskell(void)
417 {
418     hs_exit();
419 }
420
421 void
422 shutdownHaskellAndExit(int n)
423 {
424     // we're about to exit(), no need to wait for foreign calls to return.
425     hs_exit_(rtsFalse);
426
427     if (hs_init_count == 0) {
428         stg_exit(n);
429     }
430 }
431
432 #ifndef mingw32_HOST_OS
433 void
434 shutdownHaskellAndSignal(int sig)
435 {
436     hs_exit_(rtsFalse);
437     kill(getpid(),sig);
438 }
439 #endif
440
441 /* 
442  * called from STG-land to exit the program
443  */
444
445 void (*exitFn)(int) = 0;
446
447 void  
448 stg_exit(int n)
449
450   if (exitFn)
451     (*exitFn)(n);
452   exit(n);
453 }