diff --git a/src/coreclr/pal/src/include/pal/process.h b/src/coreclr/pal/src/include/pal/process.h index 1c48093af219da..d1a973d1771b69 100644 --- a/src/coreclr/pal/src/include/pal/process.h +++ b/src/coreclr/pal/src/include/pal/process.h @@ -199,6 +199,15 @@ Return --*/ BOOL InitializeFlushProcessWriteBuffers(); +/*++ +Function: + InitializeMembarrier + +Abstract + This function initializes the Linux "expedited membarrier" syscall, if available +--*/ +void InitializeMembarrier(); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/src/coreclr/pal/src/init/pal.cpp b/src/coreclr/pal/src/init/pal.cpp index 7a8fc556724c1f..478d337f128ab5 100644 --- a/src/coreclr/pal/src/init/pal.cpp +++ b/src/coreclr/pal/src/init/pal.cpp @@ -336,6 +336,10 @@ Initialize( } #endif // __APPLE__ + // Init "expedited membarrier" as soon as possible (before worker + // threads are created) for faster process startup on Linux. + InitializeMembarrier(); + CriticalSectionSubSysInitialize(); if(nullptr == init_critsec) diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index ec518417ef8386..4588164c5e0789 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -167,9 +167,10 @@ enum membarrier_cmd }; // -// Tracks if the OS supports FlushProcessWriteBuffers using membarrier +// Tracks if membarrier is initialized and available on the current system // -static int s_flushUsingMemBarrier = 0; +static BOOL s_membarrierInitialized = FALSE; +static BOOL s_membarrierAvailable = FALSE; // // Helper memory page used by the FlushProcessWriteBuffers @@ -2562,6 +2563,35 @@ PROCAbort(int signal, siginfo_t* siginfo) abort(); } +/*++ +Function: + InitializeMembarrier + +Abstract + This function initializes the Linux "expedited membarrier" syscall, if available +--*/ +void +InitializeMembarrier() +{ + if (!s_membarrierInitialized) + { + // Starting with Linux kernel 4.14, process memory barriers can be generated + // using MEMBARRIER_CMD_PRIVATE_EXPEDITED. + int mask = membarrier(MEMBARRIER_CMD_QUERY, 0); + if (mask >= 0 && + mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED) + { + // Register intent to use the private expedited command. + if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0) == 0) + { + s_membarrierAvailable = TRUE; + } + } + } + + s_membarrierInitialized = TRUE; +} + /*++ Function: InitializeFlushProcessWriteBuffers @@ -2575,20 +2605,11 @@ BOOL InitializeFlushProcessWriteBuffers() { _ASSERTE(s_helperPage == 0); - _ASSERTE(s_flushUsingMemBarrier == 0); - // Starting with Linux kernel 4.14, process memory barriers can be generated - // using MEMBARRIER_CMD_PRIVATE_EXPEDITED. - int mask = membarrier(MEMBARRIER_CMD_QUERY, 0); - if (mask >= 0 && - mask & MEMBARRIER_CMD_PRIVATE_EXPEDITED) + InitializeMembarrier(); + if (s_membarrierAvailable) { - // Register intent to use the private expedited command. - if (membarrier(MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED, 0) == 0) - { - s_flushUsingMemBarrier = TRUE; - return TRUE; - } + return TRUE; } #ifdef TARGET_OSX @@ -2645,7 +2666,7 @@ VOID PALAPI FlushProcessWriteBuffers() { - if (s_flushUsingMemBarrier) + if (s_membarrierAvailable) { int status = membarrier(MEMBARRIER_CMD_PRIVATE_EXPEDITED, 0); FATAL_ASSERT(status == 0, "Failed to flush using membarrier");