X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FRtsStartup.c;h=c9edeace8e3c94fb2257b720c30885a8831176bd;hb=de75026f5a48d3d052135a973ab4dff76c5b20f5;hp=7193876970c59c87063f1ee84f48fb38236eef46;hpb=ed12b7043fa98928f75c289a756fbcef546315f8;p=ghc-hetmet.git diff --git a/rts/RtsStartup.c b/rts/RtsStartup.c index 7193876..c9edeac 100644 --- a/rts/RtsStartup.c +++ b/rts/RtsStartup.c @@ -30,16 +30,19 @@ #include "ThreadLabels.h" #include "BlockAlloc.h" #include "Trace.h" -#include "RtsTypeable.h" +#include "RtsGlobals.h" #include "Stable.h" #include "Hpc.h" +#include "FileLock.h" +#include "EventLog.h" #if defined(RTS_GTK_FRONTPANEL) #include "FrontPanel.h" #endif -#if defined(PROFILING) || defined(DEBUG) # include "Profiling.h" + +#if defined(PROFILING) # include "ProfHeap.h" # include "RetainerProfile.h" #endif @@ -69,6 +72,9 @@ #ifdef HAVE_SIGNAL_H #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif #if USE_PAPI #include "Papi.h" @@ -138,17 +144,20 @@ hs_init(int *argc, char **argv[]) return; } -#if defined(DEBUG) - /* Start off by initialising the allocator debugging so we can - * use it anywhere */ - initAllocator(); -#endif + /* Initialise the stats department, phase 0 */ + initStats0(); /* Next we do is grab the start time...just in case we're * collecting timing statistics. */ stat_startInit(); +#if defined(DEBUG) + /* Start off by initialising the allocator debugging so we can + * use it anywhere */ + initAllocator(); +#endif + #ifdef PAR /* * The parallel system needs to be initialised and synchronised before @@ -165,30 +174,6 @@ hs_init(int *argc, char **argv[]) argv++; argc--; #endif - /* Initialise the performance tracking library */ -#ifdef USE_PAPI - { - int ver; - if ((ver = PAPI_library_init(PAPI_VER_CURRENT)) != PAPI_VER_CURRENT) { - if (ver > 0) { - errorBelch("PAPI_library_init: wrong version: %x", ver); - stg_exit(EXIT_FAILURE); - } else { - sysErrorBelch("PAPI_library_init"); - stg_exit(EXIT_FAILURE); - } - } - } -#ifdef THREADED_RTS - { - int err; - if ((err = PAPI_thread_init(osThreadId)) < 0) { - barf("PAPI_thread_init: %d",err); - } - } -#endif -#endif - /* Set the RTS flags to default values. */ initRtsFlagsDefaults(); @@ -198,12 +183,22 @@ hs_init(int *argc, char **argv[]) /* Parse the flags, separating the RTS flags from the programs args */ if (argc != NULL && argv != NULL) { + setFullProgArgv(*argc,*argv); setupRtsFlags(argc, *argv, &rts_argc, rts_argv); setProgArgv(*argc,*argv); } + /* Initialise the stats department, phase 1 */ + initStats1(); + +#ifdef USE_PAPI + papi_init(); +#endif + /* initTracing must be after setupRtsFlags() */ +#ifdef DEBUG initTracing(); +#endif #if defined(PAR) /* NB: this really must be done after processing the RTS flags */ @@ -212,9 +207,6 @@ hs_init(int *argc, char **argv[]) synchroniseSystem(); // calls initParallelSystem etc #endif /* PAR */ - /* Perform initialisation of adjustor thunk layer. */ - initAdjustor(); - /* initialise scheduler data structures (needs to be done before * initStorage()). */ @@ -236,29 +228,52 @@ hs_init(int *argc, char **argv[]) /* initialise the stable pointer table */ initStablePtrTable(); + /* Add some GC roots for things in the base package that the RTS + * knows about. We don't know whether these turn out to be CAFs + * or refer to CAFs, but we have to assume that they might. + */ + getStablePtr((StgPtr)base_GHCziTopHandler_runIO_closure); + getStablePtr((StgPtr)base_GHCziTopHandler_runNonIO_closure); + getStablePtr((StgPtr)stackOverflow_closure); + getStablePtr((StgPtr)heapOverflow_closure); + getStablePtr((StgPtr)runFinalizerBatch_closure); + getStablePtr((StgPtr)unpackCString_closure); + getStablePtr((StgPtr)blockedOnDeadMVar_closure); + getStablePtr((StgPtr)nonTermination_closure); + getStablePtr((StgPtr)blockedIndefinitely_closure); + /* initialise the shared Typeable store */ - initTypeableStore(); + initGlobalStore(); + + /* initialise file locking, if necessary */ +#if !defined(mingw32_HOST_OS) + initFileLocking(); +#endif #if defined(DEBUG) /* initialise thread label table (tso->char*) */ initThreadLabelTable(); #endif -#if defined(PROFILING) || defined(DEBUG) initProfiling1(); + +#ifdef EVENTLOG + if (RtsFlags.EventLogFlags.doEventLogging) { + initEventLogging(); + } #endif /* start the virtual timer 'subsystem'. */ + initTimer(); startTimer(); - /* Initialise the stats department */ - initStats(); - #if defined(RTS_USER_SIGNALS) - /* Initialise the user signal handler set */ - initUserSignals(); - /* Set up handler to run on SIGINT, etc. */ - initDefaultHandlers(); + if (RtsFlags.MiscFlags.install_signal_handlers) { + /* Initialise the user signal handler set */ + initUserSignals(); + /* Set up handler to run on SIGINT, etc. */ + initDefaultHandlers(); + } #endif #if defined(mingw32_HOST_OS) && !defined(THREADED_RTS) @@ -275,10 +290,6 @@ hs_init(int *argc, char **argv[]) x86_init_fpu(); #endif -#if defined(THREADED_RTS) - ioManagerStart(); -#endif - /* Record initialization times */ stat_endInit(); } @@ -328,7 +339,9 @@ hs_add_root(void (*init_root)(void)) { bdescr *bd; nat init_sp; - Capability *cap = &MainCapability; + Capability *cap; + + cap = rts_lock(); if (hs_init_count <= 0) { barf("hs_add_root() must be called after hs_init()"); @@ -351,19 +364,37 @@ hs_add_root(void (*init_root)(void)) startupHpc(); -#if defined(PROFILING) || defined(DEBUG) // This must be done after module initialisation. // ToDo: make this work in the presence of multiple hs_add_root()s. initProfiling2(); + + rts_unlock(cap); + + // ditto. +#if defined(THREADED_RTS) + ioManagerStart(); #endif } -/* ----------------------------------------------------------------------------- - Shutting down the RTS - -------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- + * Shutting down the RTS + * + * The wait_foreign parameter means: + * True ==> wait for any threads doing foreign calls now. + * False ==> threads doing foreign calls may return in the + * future, but will immediately block on a mutex. + * (capability->lock). + * + * If this RTS is a DLL that we're about to unload, then you want + * safe=True, otherwise the thread might return to code that has been + * unloaded. If this is a standalone program that is about to exit, + * then you can get away with safe=False, which is better because we + * won't hang on exit if there is a blocked foreign call outstanding. + * + ------------------------------------------------------------------------- */ -void -hs_exit(void) +static void +hs_exit_(rtsBool wait_foreign) { if (hs_init_count <= 0) { errorBelch("warning: too many hs_exit()s"); @@ -378,17 +409,24 @@ hs_exit(void) /* start timing the shutdown */ stat_startExit(); -#if defined(RTS_USER_SIGNALS) - freeSignalHandlers(); -#endif + OnExitHook(); #if defined(THREADED_RTS) ioManagerDie(); #endif /* stop all running tasks */ - exitScheduler(); + exitScheduler(wait_foreign); + + /* run C finalizers for all active weak pointers */ + runAllCFinalizers(weak_ptr_list); +#if defined(RTS_USER_SIGNALS) + if (RtsFlags.MiscFlags.install_signal_handlers) { + freeSignalHandlers(); + } +#endif + #if defined(GRAN) /* end_gr_simulation prints global stats if requested -- HWL */ if (!RtsFlags.GranFlags.GranSimStats.Suppressed) @@ -397,7 +435,8 @@ hs_exit(void) /* stop the ticker */ stopTimer(); - + exitTimer(); + /* reset the standard file descriptors to blocking mode */ resetNonBlockingFd(0); resetNonBlockingFd(1); @@ -432,6 +471,9 @@ hs_exit(void) PAR_TICKY_PAR_END(); #endif + // uninstall signal handlers + resetDefaultHandlers(); + /* stop timing the shutdown, we're about to print stats */ stat_endExit(); @@ -446,23 +488,21 @@ hs_exit(void) freeScheduler(); /* free shared Typeable store */ - exitTypeableStore(); + exitGlobalStore(); + + /* free file locking tables, if necessary */ +#if !defined(mingw32_HOST_OS) + freeFileLocking(); +#endif /* free the stable pointer table */ exitStablePtrTable(); -#if defined(PROFILING) || defined(DEBUG) - freeProfiling1(); -#endif - #if defined(DEBUG) /* free the thread label table */ freeThreadLabelTable(); #endif - /* free hash table storage */ - exitHashTable(); - #ifdef RTS_GTK_FRONTPANEL if (RtsFlags.GcFlags.frontpanel) { stopFrontPanel(); @@ -473,15 +513,21 @@ hs_exit(void) reportCCSProfiling(); #endif -#if defined(PROFILING) || defined(DEBUG) endProfiling(); -#endif + freeProfiling1(); #ifdef PROFILING // Originally, this was in report_ccs_profiling(). Now, retainer // profiling might tack some extra stuff on to the end of this file // during endProfiling(). - fclose(prof_file); + if (prof_file != NULL) fclose(prof_file); +#endif + +#ifdef EVENTLOG + if (RtsFlags.EventLogFlags.doEventLogging) { + endEventLogging(); + freeEventLogging(); + } #endif #if defined(TICKY_TICKY) @@ -489,9 +535,12 @@ hs_exit(void) #endif #if defined(mingw32_HOST_OS) && !defined(THREADED_RTS) - shutdownAsyncIO(); + shutdownAsyncIO(wait_foreign); #endif + /* free hash table storage */ + exitHashTable(); + // Finally, free all our storage freeStorage(); @@ -502,6 +551,14 @@ hs_exit(void) } +// The real hs_exit(): +void +hs_exit(void) +{ + hs_exit_(rtsTrue); + // be safe; this might be a DLL +} + // Compatibility interfaces void shutdownHaskell(void) @@ -512,9 +569,10 @@ shutdownHaskell(void) void shutdownHaskellAndExit(int n) { - if (hs_init_count == 1) { - OnExitHook(); - hs_exit(); + // we're about to exit(), no need to wait for foreign calls to return. + hs_exit_(rtsFalse); + + if (hs_init_count == 0) { #if defined(PAR) /* really exit (stg_exit() would call shutdownParallelSystem() again) */ exit(n); @@ -524,6 +582,15 @@ shutdownHaskellAndExit(int n) } } +#ifndef mingw32_HOST_OS +void +shutdownHaskellAndSignal(int sig) +{ + hs_exit_(rtsFalse); + kill(getpid(),sig); +} +#endif + /* * called from STG-land to exit the program */