Skip to content

Commit

Permalink
Enable FEATURE_PERFMAP on OSX, and update perfjitdump.cpp to work on …
Browse files Browse the repository at this point in the history
…OSX (#99986)

* Enable FEATURE_PERFMAP on OSX, and update perfjitdump.cpp to work on OSX

* Update PerfMapEnabled documentation

* Enable only on OSX, and use PlatformGetCurrentThreadId

* Manual mach_absolute_time calls

* Use QueryPerformanceCounter

* Cleaner QueryPerformanceFrequency verification

* Use FEATURE_PERFMAP

* Put back conditional, but all __APPLE__

* Fix logic error when disabling jitdump
  • Loading branch information
vvuk authored Apr 3, 2024
1 parent 995989e commit e020a93
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 34 deletions.
3 changes: 3 additions & 0 deletions src/coreclr/clrdefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,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)
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.")
Expand Down
69 changes: 36 additions & 33 deletions src/coreclr/pal/src/misc/perfjitdump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
// The .NET Foundation licenses this file to you under the MIT license.
// ===========================================================================

#if defined(__linux__)
#define JITDUMP_SUPPORTED
#endif

#include "pal/palinternal.h"
#include "pal/dbgmsg.h"

#include <cstddef>

#if defined(__linux__) || defined(__APPLE__)
#define JITDUMP_SUPPORTED
#endif

#ifdef JITDUMP_SUPPORTED

#include <fcntl.h>
Expand Down Expand Up @@ -61,24 +61,11 @@ namespace
JIT_CODE_LOAD = 0,
};

uint64_t GetTimeStampNS()
static uint64_t GetTimeStampNS()
{
#if 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
{
return ts.tv_sec * 1000000000ULL + ts.tv_nsec;
}
#else
#error "The PAL jitdump requires clock_gettime(CLOCK_MONOTONIC) to be supported."
#endif
LARGE_INTEGER result;
QueryPerformanceCounter(&result);
return result.QuadPart;
}

struct FileHeader
Expand Down Expand Up @@ -115,7 +102,7 @@ namespace
{
JitCodeLoadRecord() :
pid(getpid()),
tid(syscall(SYS_gettid))
tid((uint32_t)PlatformGetCurrentThreadId())
{
header.id = JIT_CODE_LOAD;
header.timestamp = GetTimeStampNS();
Expand Down Expand Up @@ -170,6 +157,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;

Expand Down Expand Up @@ -203,12 +203,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;

Expand Down Expand Up @@ -308,16 +314,13 @@ struct PerfJitDumpState
{
enabled = false;

if (result != 0)
return FatalError();

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;

Expand All @@ -333,7 +336,7 @@ struct PerfJitDumpState

fd = -1;
}
exit:

return 0;
}
};
Expand Down

0 comments on commit e020a93

Please sign in to comment.