From 3be6d5910416e738384d83f89d3de8a0f647ead9 Mon Sep 17 00:00:00 2001 From: Duncan Coutts <duncan@well-typed.com> Date: Mon, 9 Jan 2023 17:06:28 +0000 Subject: [PATCH] Select an I/O manager early in RTS startup We need to select the I/O manager to use during startup before the per-cap I/O manager initialisation. --- rts/Capability.c | 2 +- rts/IOManager.c | 21 +++++++++++++-------- rts/IOManager.h | 14 +++++++++++--- rts/RtsStartup.c | 3 +++ 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/rts/Capability.c b/rts/Capability.c index c8e15c178d56..a9fe393a08db 100644 --- a/rts/Capability.c +++ b/rts/Capability.c @@ -281,7 +281,7 @@ initCapability (Capability *cap, uint32_t i) #endif cap->total_allocated = 0; - initCapabilityIOManager(&cap->iomgr); + initCapabilityIOManager(cap); /* initialises cap->iomgr */ cap->f.stgEagerBlackholeInfo = (W_)&__stg_EAGER_BLACKHOLE_info; cap->f.stgGCEnter1 = (StgFunPtr)__stg_gc_enter_1; diff --git a/rts/IOManager.c b/rts/IOManager.c index e6db47fa50fe..e0e4ef04ac2e 100644 --- a/rts/IOManager.c +++ b/rts/IOManager.c @@ -174,8 +174,11 @@ parseIOManagerFlag(const char *iomgrstr, IO_MANAGER_FLAG *flag) * * This fills in the iomgr_type and rts_IOManagerIsWin32Native globals. * Must be called before the I/O manager is started. + * + * Called early in the RTS initialisation, after the RTS flags have been + * processed. */ -static void selectIOManager(void) +void selectIOManager(void) { switch (RtsFlags.MiscFlags.ioManager) { case IO_MNGR_FLAG_AUTO: @@ -242,9 +245,13 @@ static void selectIOManager(void) /* Allocate and initialise the per-capability CapIOManager that lives in each - * Capability. Called early in the RTS initialisation. + * Capability. Called from initCapability(), which is done in the RTS startup + * in initCapabilities(), and later at runtime via setNumCapabilities(). + * + * Note that during RTS startup this is called _before_ the storage manager + * is initialised, so this is not allowed to allocate on the GC heap. */ -void initCapabilityIOManager(CapIOManager **piomgr) +void initCapabilityIOManager(Capability *cap) { CapIOManager *iomgr = (CapIOManager *) stgMallocBytes(sizeof(CapIOManager), @@ -275,20 +282,18 @@ void initCapabilityIOManager(CapIOManager **piomgr) break; } - *piomgr = iomgr; + cap->iomgr = iomgr; } /* Called late in the RTS initialisation */ -void -initIOManager(void) +void initIOManager(void) { - selectIOManager(); switch (iomgr_type) { - /* The IO_MANAGER_SELECT needs no initialisation */ + /* The IO_MANAGER_SELECT needs no global initialisation */ #if defined(IOMGR_ENABLED_MIO_POSIX) case IO_MANAGER_MIO_POSIX: diff --git a/rts/IOManager.h b/rts/IOManager.h index 24218e9315d0..b54dbd0974d1 100644 --- a/rts/IOManager.h +++ b/rts/IOManager.h @@ -214,11 +214,19 @@ typedef struct { } CapIOManager; +/* Init hook: called from hs_init_ghc, early in the startup after the RTS flags + * have been processed. + * + * Based on the I/O manager RTS flag, select an I/O manager to use. + */ +void selectIOManager(void); + + /* Allocate and initialise the per-capability CapIOManager that lives in each - * Capability. It is called from initCapability, via initScheduler, - * via hs_init_ghc. + * Capability. Called from initCapability(), which is done in the RTS startup + * in initCapabilities(), and later at runtime via setNumCapabilities(). */ -void initCapabilityIOManager(CapIOManager **iomgr); +void initCapabilityIOManager(Capability *cap); /* Init hook: called from hs_init_ghc, very late in the startup after almost diff --git a/rts/RtsStartup.c b/rts/RtsStartup.c index cfbd0421f5d4..70e926b44623 100644 --- a/rts/RtsStartup.c +++ b/rts/RtsStartup.c @@ -331,6 +331,9 @@ hs_init_ghc(int *argc, char **argv[], RtsConfig rts_config) #endif /* DEBUG */ } + /* Based on the RTS flags, decide which I/O manager to use. */ + selectIOManager(); + /* Initialize console Codepage. */ #if defined(mingw32_HOST_OS) if (is_io_mng_native_p()) -- GitLab