+ - we register stable names for each foreign-exported function
+ in that module. This prevents foreign-exported entities, and
+ things they depend on, from being garbage collected.
+
+ - we supply a unique integer to each statically declared cost
+ centre and cost centre stack in the program.
+
+ The code generator inserts a small function "__stginit_<module>" in each
+ module and calls the registration functions in each of the modules it
+ imports.
+
+ The init* functions are compiled in the same way as STG code,
+ i.e. without normal C call/return conventions. Hence we must use
+ StgRun to call this stuff.
+ -------------------------------------------------------------------------- */
+
+/* The init functions use an explicit stack...
+ */
+#define INIT_STACK_BLOCKS 4
+static F_ *init_stack = NULL;
+
+void
+hs_add_root(void (*init_root)(void))
+{
+ bdescr *bd;
+ nat init_sp;
+ Capability *cap = &MainCapability;
+
+ if (hs_init_count <= 0) {
+ barf("hs_add_root() must be called after hs_init()");
+ }
+
+ /* The initialisation stack grows downward, with sp pointing
+ to the last occupied word */
+ init_sp = INIT_STACK_BLOCKS*BLOCK_SIZE_W;
+ bd = allocGroup_lock(INIT_STACK_BLOCKS);
+ init_stack = (F_ *)bd->start;
+ init_stack[--init_sp] = (F_)stg_init_finish;
+ if (init_root != NULL) {
+ init_stack[--init_sp] = (F_)init_root;
+ }
+
+ cap->r.rSp = (P_)(init_stack + init_sp);
+ StgRun((StgFunPtr)stg_init, &cap->r);
+
+ freeGroup_lock(bd);
+
+#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();
+#endif
+}
+
+/* -----------------------------------------------------------------------------
+ Shutting down the RTS
+ -------------------------------------------------------------------------- */
+
+void
+hs_exit(void)
+{
+ if (hs_init_count <= 0) {
+ barf("too many hs_exit()s");
+ }
+ hs_init_count--;
+ if (hs_init_count > 0) {
+ // ignore until it's the last one
+ return;
+ }
+
+ /* start timing the shutdown */
+ stat_startExit();
+
+ /* stop all running tasks */
+ exitScheduler();
+