Enable pthread_getspecific() tls for LLVM compiler
[ghc.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 /* Trace some basic information about the process */
157 traceOSProcessInfo();
158
159 /* initialize the storage manager */
160 initStorage();
161
162 /* initialise the stable pointer table */
163 initStablePtrTable();
164
165 /* Add some GC roots for things in the base package that the RTS
166 * knows about. We don't know whether these turn out to be CAFs
167 * or refer to CAFs, but we have to assume that they might.
168 */
169 getStablePtr((StgPtr)runIO_closure);
170 getStablePtr((StgPtr)runNonIO_closure);
171
172 getStablePtr((StgPtr)runFinalizerBatch_closure);
173
174 getStablePtr((StgPtr)stackOverflow_closure);
175 getStablePtr((StgPtr)heapOverflow_closure);
176 getStablePtr((StgPtr)unpackCString_closure);
177 getStablePtr((StgPtr)blockedIndefinitelyOnMVar_closure);
178 getStablePtr((StgPtr)nonTermination_closure);
179 getStablePtr((StgPtr)blockedIndefinitelyOnSTM_closure);
180 getStablePtr((StgPtr)nestedAtomically_closure);
181
182 getStablePtr((StgPtr)runSparks_closure);
183 getStablePtr((StgPtr)ensureIOManagerIsRunning_closure);
184 #ifndef mingw32_HOST_OS
185 getStablePtr((StgPtr)runHandlers_closure);
186 #endif
187
188 /* initialise the shared Typeable store */
189 initGlobalStore();
190
191 /* initialise file locking, if necessary */
192 #if !defined(mingw32_HOST_OS)
193 initFileLocking();
194 #endif
195
196 #if defined(DEBUG)
197 /* initialise thread label table (tso->char*) */
198 initThreadLabelTable();
199 #endif
200
201 initProfiling1();
202
203 /* start the virtual timer 'subsystem'. */
204 initTimer();
205 startTimer();
206
207 #if defined(RTS_USER_SIGNALS)
208 if (RtsFlags.MiscFlags.install_signal_handlers) {
209 /* Initialise the user signal handler set */
210 initUserSignals();
211 /* Set up handler to run on SIGINT, etc. */
212 initDefaultHandlers();
213 }
214 #endif
215
216 #if defined(mingw32_HOST_OS) && !defined(THREADED_RTS)
217 startupAsyncIO();
218 #endif
219
220 #ifdef RTS_GTK_FRONTPANEL
221 if (RtsFlags.GcFlags.frontpanel) {
222 initFrontPanel();
223 }
224 #endif
225
226 #if X86_INIT_FPU
227 x86_init_fpu();
228 #endif
229
230 startupHpc();
231
232 // This must be done after module initialisation.
233 // ToDo: make this work in the presence of multiple hs_add_root()s.
234 initProfiling2();
235
236 // ditto.
237 #if defined(THREADED_RTS)
238 ioManagerStart();
239 #endif
240
241 /* Record initialization times */
242 stat_endInit();
243 }
244
245 // Compatibility interface
246 void
247 startupHaskell(int argc, char *argv[], void (*init_root)(void) STG_UNUSED)
248 {
249 hs_init(&argc, &argv);
250 }
251
252
253 /* -----------------------------------------------------------------------------
254 hs_add_root: backwards compatibility. (see #3252)
255 -------------------------------------------------------------------------- */
256
257 void
258 hs_add_root(void (*init_root)(void) STG_UNUSED)
259 {
260 /* nothing */
261 }
262
263 /* ----------------------------------------------------------------------------
264 * Shutting down the RTS
265 *
266 * The wait_foreign parameter means:
267 * True ==> wait for any threads doing foreign calls now.
268 * False ==> threads doing foreign calls may return in the
269 * future, but will immediately block on a mutex.
270 * (capability->lock).
271 *
272 * If this RTS is a DLL that we're about to unload, then you want
273 * safe=True, otherwise the thread might return to code that has been
274 * unloaded. If this is a standalone program that is about to exit,
275 * then you can get away with safe=False, which is better because we
276 * won't hang on exit if there is a blocked foreign call outstanding.
277 *
278 ------------------------------------------------------------------------- */
279
280 static void
281 hs_exit_(rtsBool wait_foreign)
282 {
283 if (hs_init_count <= 0) {
284 errorBelch("warning: too many hs_exit()s");
285 return;
286 }
287 hs_init_count--;
288 if (hs_init_count > 0) {
289 // ignore until it's the last one
290 return;
291 }
292
293 /* start timing the shutdown */
294 stat_startExit();
295
296 OnExitHook();
297
298 // sanity check
299 #if defined(DEBUG)
300 checkFPUStack();
301 #endif
302
303 #if defined(THREADED_RTS)
304 ioManagerDie();
305 #endif
306
307 /* stop all running tasks */
308 exitScheduler(wait_foreign);
309
310 /* run C finalizers for all active weak pointers */
311 runAllCFinalizers(weak_ptr_list);
312
313 #if defined(RTS_USER_SIGNALS)
314 if (RtsFlags.MiscFlags.install_signal_handlers) {
315 freeSignalHandlers();
316 }
317 #endif
318
319 /* stop the ticker */
320 stopTimer();
321 exitTimer(wait_foreign);
322
323 // set the terminal settings back to what they were
324 #if !defined(mingw32_HOST_OS)
325 resetTerminalSettings();
326 #endif
327
328 // uninstall signal handlers
329 resetDefaultHandlers();
330
331 /* stop timing the shutdown, we're about to print stats */
332 stat_endExit();
333
334 /* shutdown the hpc support (if needed) */
335 exitHpc();
336
337 // clean up things from the storage manager's point of view.
338 // also outputs the stats (+RTS -s) info.
339 exitStorage();
340
341 /* free the tasks */
342 freeScheduler();
343
344 /* free shared Typeable store */
345 exitGlobalStore();
346
347 /* free linker data */
348 exitLinker();
349
350 /* free file locking tables, if necessary */
351 #if !defined(mingw32_HOST_OS)
352 freeFileLocking();
353 #endif
354
355 /* free the stable pointer table */
356 exitStablePtrTable();
357
358 #if defined(DEBUG)
359 /* free the thread label table */
360 freeThreadLabelTable();
361 #endif
362
363 #ifdef RTS_GTK_FRONTPANEL
364 if (RtsFlags.GcFlags.frontpanel) {
365 stopFrontPanel();
366 }
367 #endif
368
369 #if defined(PROFILING)
370 reportCCSProfiling();
371 #endif
372
373 endProfiling();
374 freeProfiling();
375
376 #ifdef PROFILING
377 // Originally, this was in report_ccs_profiling(). Now, retainer
378 // profiling might tack some extra stuff on to the end of this file
379 // during endProfiling().
380 if (prof_file != NULL) fclose(prof_file);
381 #endif
382
383 #ifdef TRACING
384 endTracing();
385 freeTracing();
386 #endif
387
388 #if defined(TICKY_TICKY)
389 if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
390 #endif
391
392 #if defined(mingw32_HOST_OS) && !defined(THREADED_RTS)
393 shutdownAsyncIO(wait_foreign);
394 #endif
395
396 /* free hash table storage */
397 exitHashTable();
398
399 // Finally, free all our storage. However, we only free the heap
400 // memory if we have waited for foreign calls to complete;
401 // otherwise a foreign call in progress may still be referencing
402 // heap memory (e.g. by being passed a ByteArray#).
403 freeStorage(wait_foreign);
404
405 // Free the various argvs
406 freeRtsArgs();
407 }
408
409 // The real hs_exit():
410 void
411 hs_exit(void)
412 {
413 hs_exit_(rtsTrue);
414 // be safe; this might be a DLL
415 }
416
417 // Compatibility interfaces
418 void
419 shutdownHaskell(void)
420 {
421 hs_exit();
422 }
423
424 void
425 shutdownHaskellAndExit(int n)
426 {
427 // even if hs_init_count > 1, we still want to shut down the RTS
428 // and exit immediately (see #5402)
429 hs_init_count = 1;
430
431 // we're about to exit(), no need to wait for foreign calls to return.
432 hs_exit_(rtsFalse);
433
434 stg_exit(n);
435 }
436
437 #ifndef mingw32_HOST_OS
438 void
439 shutdownHaskellAndSignal(int sig)
440 {
441 hs_exit_(rtsFalse);
442 kill(getpid(),sig);
443 }
444 #endif
445
446 /*
447 * called from STG-land to exit the program
448 */
449
450 void (*exitFn)(int) = 0;
451
452 void
453 stg_exit(int n)
454 {
455 if (exitFn)
456 (*exitFn)(n);
457 exit(n);
458 }