From 29069d461ed711a3d4f3bf64527985e239d07ccf Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Mon, 18 Mar 2024 16:48:59 -0700 Subject: [PATCH 01/13] Enable FEATURE_PERFMAP on OSX, and update perfjitdump.cpp to work on OSX --- src/coreclr/clrdefinitions.cmake | 3 ++ src/coreclr/pal/src/misc/perfjitdump.cpp | 37 ++++++++++++++++++++---- 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index 2ffcfb00c0c05..e7afa4483789d 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -154,6 +154,9 @@ endif(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX) if(CLR_CMAKE_TARGET_FREEBSD) add_compile_definitions(FEATURE_PERFMAP) endif(CLR_CMAKE_TARGET_FREEBSD) +if(CLR_CMAKE_TARGET_APPLE) + add_compile_definitions(FEATURE_PERFMAP) +endif(CLR_CMAKE_TARGET_APPLE) if(FEATURE_COMWRAPPERS) add_compile_definitions(FEATURE_COMWRAPPERS) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 50b0f2c6dadcf..05e621a38f1a2 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== -#if defined(__linux__) +#if defined(__linux__) || defined(__APPLE__) #define JITDUMP_SUPPORTED #endif @@ -61,6 +61,22 @@ namespace JIT_CODE_LOAD = 0, }; +#if defined(__linux__) + static uint32_t sys_gettid() + { + return syscall(SYS_gettid); + } +#else + static uint32_t sys_gettid() + { + // macOS SYS_gettid is completely unrelated to linux gettid (it returns + // effective uid/gid a thread is operating under) + // There is pthread_threadid_np(), but it returns a uint64_t. + // Given that we need a uint32_t, just return 0 here for now. + return 0; + } +#endif + uint64_t GetTimeStampNS() { #if HAVE_CLOCK_MONOTONIC @@ -115,7 +131,7 @@ namespace { JitCodeLoadRecord() : pid(getpid()), - tid(syscall(SYS_gettid)) + tid(sys_gettid()) { header.id = JIT_CODE_LOAD; header.timestamp = GetTimeStampNS(); @@ -203,12 +219,18 @@ struct PerfJitDumpState if (result == -1) return FatalError(); +#if !defined(__APPLE__) // mmap jitdump file - // this is a marker for perf inject to find the jitdumpfile + // this is a marker for perf inject to find the jitdumpfile on linux. + // On OSX, samply and others hook open and mmap is not needed. It also fails on OSX, + // likely because of PROT_EXEC and hardened runtime mmapAddr = mmap(nullptr, sizeof(FileHeader), PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0); if (mmapAddr == MAP_FAILED) return FatalError(); +#else + mmapAddr = NULL; +#endif enabled = true; @@ -314,10 +336,13 @@ struct PerfJitDumpState if (!enabled) goto exit; - result = munmap(mmapAddr, sizeof(FileHeader)); + if (mmapAddr != NULL) + { + result = munmap(mmapAddr, sizeof(FileHeader)); - if (result == -1) - return FatalError(); + if (result == -1) + return FatalError(); + } mmapAddr = MAP_FAILED; From c3333a6cb4a2ac4d17d3c201ad6dd840c849b40f Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Thu, 21 Mar 2024 06:03:35 -0700 Subject: [PATCH 02/13] Update PerfMapEnabled documentation --- src/coreclr/inc/clrconfigvalues.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 45674a77c3539..4f4ee01c50182 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -480,7 +480,7 @@ RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_ETW_ObjectAllocationEventsPerTypePerSec, W RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_ProfAPI_ValidateNGENInstrumentation, W("ProfAPI_ValidateNGENInstrumentation"), 0, "This flag enables additional validations when using the IMetaDataEmit APIs for NGEN'ed images to ensure only supported edits are made.") #ifdef FEATURE_PERFMAP -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux to enable writing /tmp/perf-$pid.map. It is disabled by default") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapEnabled, W("PerfMapEnabled"), 0, "This flag is used on Linux and macOS to enable writing /tmp/perf-$pid.map. It is disabled by default") RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_PerfMapJitDumpPath, W("PerfMapJitDumpPath"), "Specifies a path to write the perf jitdump file. Defaults to /tmp", CLRConfig::LookupOptions::TrimWhiteSpaceFromStringValue) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapIgnoreSignal, W("PerfMapIgnoreSignal"), 0, "When perf map is enabled, this option will configure the specified signal to be accepted and ignored as a marker in the perf logs. It is disabled by default") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_PerfMapShowOptimizationTiers, W("PerfMapShowOptimizationTiers"), 1, "Shows optimization tiers in the perf map for methods, as part of the symbol name. Useful for seeing separate stack frames for different optimization tiers of each method.") From f1c828b4e569e91c9bc60a9f37cca93d2e62f19c Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Sun, 24 Mar 2024 23:20:48 -0500 Subject: [PATCH 03/13] Enable only on OSX, and use PlatformGetCurrentThreadId --- src/coreclr/pal/src/misc/perfjitdump.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 05e621a38f1a2..43a04121b789d 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -11,6 +11,10 @@ #include +#if defined(__linux__) || (defined(__APPLE__) && defined(TARGET_OS_OSX) && TARGET_OS_OSX) +#define JITDUMP_SUPPORTED +#endif + #ifdef JITDUMP_SUPPORTED #include @@ -131,7 +135,7 @@ namespace { JitCodeLoadRecord() : pid(getpid()), - tid(sys_gettid()) + tid((uint32_t)PlatformGetCurrentThreadId()) { header.id = JIT_CODE_LOAD; header.timestamp = GetTimeStampNS(); From e21e2f1b363e3dbf79db19cebbf62273c172b290 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Sun, 24 Mar 2024 23:21:28 -0500 Subject: [PATCH 04/13] Manual mach_absolute_time calls --- src/coreclr/pal/src/misc/perfjitdump.cpp | 45 ++++++++++++------------ 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 43a04121b789d..da85bbcde7599 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -2,10 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // =========================================================================== -#if defined(__linux__) || defined(__APPLE__) -#define JITDUMP_SUPPORTED -#endif - #include "pal/palinternal.h" #include "pal/dbgmsg.h" @@ -31,6 +27,10 @@ #include #include +#if defined(__APPLE__) +#include +#endif + #include "../inc/llvm/ELF.h" SET_DEFAULT_DEBUG_CHANNEL(MISC); @@ -65,25 +65,26 @@ namespace JIT_CODE_LOAD = 0, }; -#if defined(__linux__) - static uint32_t sys_gettid() - { - return syscall(SYS_gettid); - } -#else - static uint32_t sys_gettid() - { - // macOS SYS_gettid is completely unrelated to linux gettid (it returns - // effective uid/gid a thread is operating under) - // There is pthread_threadid_np(), but it returns a uint64_t. - // Given that we need a uint32_t, just return 0 here for now. - return 0; - } -#endif - uint64_t GetTimeStampNS() { -#if HAVE_CLOCK_MONOTONIC +#if defined(__APPLE__) + // This is the same value as CLOCK_UPTIME_RAW returns, but it's not clear + // if it caches the timebase_info conversion. Just call the mach functions + // directly. + static mach_timebase_info_data_t info = { 0, 0 }; + if (info.denom == 0) + { + int result = mach_timebase_info(&info); + if (result != 0 || info.denom == 0) { + info.numer = 1; + info.denom = 1; + } + } + + uint64_t time = mach_absolute_time(); + + return time * uint64_t(info.numer) / uint64_t(info.denom); +#elif HAVE_CLOCK_MONOTONIC struct timespec ts; int result = clock_gettime(CLOCK_MONOTONIC, &ts); @@ -97,7 +98,7 @@ namespace return ts.tv_sec * 1000000000ULL + ts.tv_nsec; } #else - #error "The PAL jitdump requires clock_gettime(CLOCK_MONOTONIC) to be supported." + #error "The PAL jitdump requires clock_gettime(CLOCK_MONOTONIC) or another way of obtaining monotonic time to be supported." #endif } From 98fe8d6881b24521cad72699c8ff4401aa1c7d79 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Sun, 24 Mar 2024 23:33:19 -0500 Subject: [PATCH 05/13] Use QueryPerformanceCounter --- src/coreclr/pal/src/misc/perfjitdump.cpp | 45 ++++++++---------------- 1 file changed, 15 insertions(+), 30 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index da85bbcde7599..36523eb0c4bb7 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -67,39 +67,24 @@ namespace uint64_t GetTimeStampNS() { -#if defined(__APPLE__) - // This is the same value as CLOCK_UPTIME_RAW returns, but it's not clear - // if it caches the timebase_info conversion. Just call the mach functions - // directly. - static mach_timebase_info_data_t info = { 0, 0 }; - if (info.denom == 0) - { - int result = mach_timebase_info(&info); - if (result != 0 || info.denom == 0) { - info.numer = 1; - info.denom = 1; - } - } - - uint64_t time = mach_absolute_time(); - - return time * uint64_t(info.numer) / uint64_t(info.denom); -#elif HAVE_CLOCK_MONOTONIC - struct timespec ts; - int result = clock_gettime(CLOCK_MONOTONIC, &ts); - - if (result != 0) - { - ASSERT("clock_gettime(CLOCK_MONOTONIC) failed: %d\n", result); - return 0; - } - else +#if defined(_DEBUG) + static bool freq_valid = false; + if (!freq_valid) { - return ts.tv_sec * 1000000000ULL + ts.tv_nsec; + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + // On platforms where JITDUMP is used, the PAL QueryPerformanceFrequency + // returns tccSecondsToNanoSeconds, meaning QueryPerformanceCounter + // will return a direct nanosecond value. If this isn't true, + // then some other method will need to be used to implement GetTimeStampNS. + ASSERT(freq.QuadPart == tccSecondsToNanoSeconds); + freq_valid = true; } -#else - #error "The PAL jitdump requires clock_gettime(CLOCK_MONOTONIC) or another way of obtaining monotonic time to be supported." #endif + + LARGE_INTEGER result; + QueryPerformanceCounter(&result); + return result.QuadPart; } struct FileHeader From 7fb18e55be487f0081febd0191190eb1b40051d7 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Sun, 24 Mar 2024 23:40:56 -0500 Subject: [PATCH 06/13] Cleaner QueryPerformanceFrequency verification --- src/coreclr/pal/src/misc/perfjitdump.cpp | 30 +++++++++++------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 36523eb0c4bb7..a6957e6812943 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -65,23 +65,8 @@ namespace JIT_CODE_LOAD = 0, }; - uint64_t GetTimeStampNS() + static uint64_t GetTimeStampNS() { -#if defined(_DEBUG) - static bool freq_valid = false; - if (!freq_valid) - { - LARGE_INTEGER freq; - QueryPerformanceFrequency(&freq); - // On platforms where JITDUMP is used, the PAL QueryPerformanceFrequency - // returns tccSecondsToNanoSeconds, meaning QueryPerformanceCounter - // will return a direct nanosecond value. If this isn't true, - // then some other method will need to be used to implement GetTimeStampNS. - ASSERT(freq.QuadPart == tccSecondsToNanoSeconds); - freq_valid = true; - } -#endif - LARGE_INTEGER result; QueryPerformanceCounter(&result); return result.QuadPart; @@ -176,6 +161,19 @@ struct PerfJitDumpState { int result = 0; + // On platforms where JITDUMP is used, the PAL QueryPerformanceFrequency + // returns tccSecondsToNanoSeconds, meaning QueryPerformanceCounter + // will return a direct nanosecond value. If this isn't true, + // then some other method will need to be used to implement GetTimeStampNS. + // Validate this is true once in Start here. + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + if (freq.QuadPart != tccSecondsToNanoSeconds) + { + _ASSERTE(!"QueryPerformanceFrequency does not return tccSecondsToNanoSeconds. Implement JITDUMP GetTimeStampNS directly for this platform.\n"); + FatalError(); + } + // Write file header FileHeader header; From 8a25906fce119ab9899fee50e78e8625a66e478b Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Mon, 25 Mar 2024 13:24:08 -0500 Subject: [PATCH 07/13] Use FEATURE_PERFMAP --- src/coreclr/pal/src/misc/perfjitdump.cpp | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index a6957e6812943..c049ca7fd3f96 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -7,11 +7,7 @@ #include -#if defined(__linux__) || (defined(__APPLE__) && defined(TARGET_OS_OSX) && TARGET_OS_OSX) -#define JITDUMP_SUPPORTED -#endif - -#ifdef JITDUMP_SUPPORTED +#ifdef FEATURE_PERFMAP #include #include @@ -27,10 +23,6 @@ #include #include -#if defined(__APPLE__) -#include -#endif - #include "../inc/llvm/ELF.h" SET_DEFAULT_DEBUG_CHANNEL(MISC); From 157a685c93eff89a932370b64c290e49d1d5d4ec Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Mon, 25 Mar 2024 13:25:37 -0500 Subject: [PATCH 08/13] Remove stubs --- src/coreclr/pal/src/misc/perfjitdump.cpp | 32 +----------------------- 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index c049ca7fd3f96..078e6916addc5 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -379,34 +379,4 @@ PAL_PerfJitDump_Finish() return GetState().Finish(); } -#else // JITDUMP_SUPPORTED - -int -PALAPI -PAL_PerfJitDump_Start(const char* path) -{ - return 0; -} - -bool -PALAPI -PAL_PerfJitDump_IsStarted() -{ - return false; -} - -int -PALAPI -PAL_PerfJitDump_LogMethod(void* pCode, size_t codeSize, const char* symbol, void* debugInfo, void* unwindInfo) -{ - return 0; -} - -int -PALAPI -PAL_PerfJitDump_Finish() -{ - return 0; -} - -#endif // JITDUMP_SUPPORTED +#endif // FEATURE_PERFMAP From 315c197497c2a3e852dba1f6664c3a5ecb49faf7 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Mon, 25 Mar 2024 13:31:40 -0500 Subject: [PATCH 09/13] Revert "Remove stubs" This reverts commit 157a685c93eff89a932370b64c290e49d1d5d4ec. --- src/coreclr/pal/src/misc/perfjitdump.cpp | 32 +++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 078e6916addc5..c049ca7fd3f96 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -379,4 +379,34 @@ PAL_PerfJitDump_Finish() return GetState().Finish(); } -#endif // FEATURE_PERFMAP +#else // JITDUMP_SUPPORTED + +int +PALAPI +PAL_PerfJitDump_Start(const char* path) +{ + return 0; +} + +bool +PALAPI +PAL_PerfJitDump_IsStarted() +{ + return false; +} + +int +PALAPI +PAL_PerfJitDump_LogMethod(void* pCode, size_t codeSize, const char* symbol, void* debugInfo, void* unwindInfo) +{ + return 0; +} + +int +PALAPI +PAL_PerfJitDump_Finish() +{ + return 0; +} + +#endif // JITDUMP_SUPPORTED From c901cb6b82fb36079020e31296c53d30ce7a79ce Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Mon, 25 Mar 2024 13:32:33 -0500 Subject: [PATCH 10/13] Put back conditional, but all __APPLE__ --- src/coreclr/pal/src/misc/perfjitdump.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index c049ca7fd3f96..986be299fba78 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -7,7 +7,11 @@ #include -#ifdef FEATURE_PERFMAP +#if defined(__linux__) || defined(__APPLE__) +#define JITDUMP_SUPPORTED +#endif + +#ifdef JITDUMP_SUPPORTED #include #include From d606bccf8076695787aa48c75f1b08ef0f1cb318 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Mon, 1 Apr 2024 16:58:52 -0700 Subject: [PATCH 11/13] Fix logic error when disabling jitdump --- src/coreclr/pal/src/misc/perfjitdump.cpp | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 986be299fba78..6223d533ac7f7 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -314,12 +314,6 @@ struct PerfJitDumpState { enabled = false; - if (result != 0) - return FatalError(); - - if (!enabled) - goto exit; - if (mmapAddr != NULL) { result = munmap(mmapAddr, sizeof(FileHeader)); @@ -342,7 +336,7 @@ struct PerfJitDumpState fd = -1; } -exit: + return 0; } }; From 3657586cff4bc81751068ce1fc4c7e90fe1f3746 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 2 Apr 2024 06:55:25 -0700 Subject: [PATCH 12/13] Skip cleanup entirely --- src/coreclr/pal/src/misc/perfjitdump.cpp | 32 ++++-------------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 6223d533ac7f7..9df9ba5145d0e 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -308,34 +308,12 @@ struct PerfJitDumpState int Finish() { - int result = 0; - - if (enabled) - { - enabled = false; - - if (mmapAddr != NULL) - { - result = munmap(mmapAddr, sizeof(FileHeader)); - - if (result == -1) - return FatalError(); - } - - mmapAddr = MAP_FAILED; - - result = fsync(fd); - - if (result == -1) - return FatalError(); - - result = close(fd); + // There's no way to cleanly shut down (munmap and close the fd) without + // adding locks, which would slow down a hot operation. We deliberately + // skip cleanup here and let the OS take care of releasing resources on + // process exit. - if (result == -1) - return FatalError(); - - fd = -1; - } + enabled = false; return 0; } From e643af706a846aa45f4441e4f1023ece44971218 Mon Sep 17 00:00:00 2001 From: Vladimir Vukicevic Date: Tue, 2 Apr 2024 12:44:48 -0700 Subject: [PATCH 13/13] Revert "Skip cleanup entirely" This reverts commit 3657586cff4bc81751068ce1fc4c7e90fe1f3746. --- src/coreclr/pal/src/misc/perfjitdump.cpp | 32 ++++++++++++++++++++---- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/src/coreclr/pal/src/misc/perfjitdump.cpp b/src/coreclr/pal/src/misc/perfjitdump.cpp index 9df9ba5145d0e..6223d533ac7f7 100644 --- a/src/coreclr/pal/src/misc/perfjitdump.cpp +++ b/src/coreclr/pal/src/misc/perfjitdump.cpp @@ -308,12 +308,34 @@ struct PerfJitDumpState int Finish() { - // There's no way to cleanly shut down (munmap and close the fd) without - // adding locks, which would slow down a hot operation. We deliberately - // skip cleanup here and let the OS take care of releasing resources on - // process exit. + int result = 0; - enabled = false; + if (enabled) + { + enabled = false; + + if (mmapAddr != NULL) + { + result = munmap(mmapAddr, sizeof(FileHeader)); + + if (result == -1) + return FatalError(); + } + + mmapAddr = MAP_FAILED; + + result = fsync(fd); + + if (result == -1) + return FatalError(); + + result = close(fd); + + if (result == -1) + return FatalError(); + + fd = -1; + } return 0; }