Skip to content

Commit

Permalink
Merge pull request #4260 from Sonicadvance1/profile_win32
Browse files Browse the repository at this point in the history
Profiler: Setup for usage on Windows
  • Loading branch information
lioncash authored Jan 15, 2025
2 parents 48c03d7 + 4c9f1b1 commit 8e2b4a3
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 25 deletions.
56 changes: 41 additions & 15 deletions FEXCore/Source/Utils/Profiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <linux/magic.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <time.h>
#endif

#include <FEXCore/Utils/LogManager.h>
Expand All @@ -18,6 +19,36 @@
#define BACKEND_GPUVIS 1

#ifdef ENABLE_FEXCORE_PROFILER
#ifndef _WIN32
static inline uint64_t GetTime() {
// We want the time in the least amount of overhead possible
// clock_gettime will do a VDSO call with the least amount of overhead
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1'000'000'000ULL + ts.tv_nsec;
}
#else

static inline uint64_t GetTime() {
// GetTime needs to return nanoseconds, query the interface.
static uint64_t FrequencyScale = {};
if (!FrequencyScale) [[unlikely]] {
LARGE_INTEGER Frequency {};
while (!QueryPerformanceFrequency(&Frequency))
;
constexpr uint64_t NanosecondsInSecond = 1'000'000'000ULL;

// On WINE this will always result in a scale of 100.
FrequencyScale = NanosecondsInSecond / Frequency.QuadPart;
}
LARGE_INTEGER ticks;
while (!QueryPerformanceCounter(&ticks))
;
return ticks.QuadPart * FrequencyScale;
}

#endif

#if FEXCORE_PROFILER_BACKEND == BACKEND_GPUVIS
namespace FEXCore::Profiler {
ProfilerBlock::ProfilerBlock(std::string_view const Format)
Expand All @@ -41,23 +72,18 @@ static std::array<const char*, 2> TraceFSDirectories {
"/sys/kernel/debug/tracing",
};

static bool IsTraceFS(const char* Path) {
struct statfs stat;
if (statfs(Path, &stat)) {
return false;
}
return stat.f_type == TRACEFS_MAGIC;
}

void Init() {
for (auto Path : TraceFSDirectories) {
if (IsTraceFS(Path)) {
fextl::string FilePath = fextl::fmt::format("{}/trace_marker", Path);
TraceFD = open(FilePath.c_str(), O_WRONLY | O_CLOEXEC);
if (TraceFD != -1) {
// Opened TraceFD, early exit
break;
}
#ifdef _WIN32
constexpr auto flags = O_WRONLY;
#else
constexpr auto flags = O_WRONLY | O_CLOEXEC;
#endif
fextl::string FilePath = fextl::fmt::format("{}/trace_marker", Path);
TraceFD = open(FilePath.c_str(), flags);
if (TraceFD != -1) {
// Opened TraceFD, early exit
break;
}
}
}
Expand Down
9 changes: 0 additions & 9 deletions FEXCore/include/FEXCore/Utils/Profiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#pragma once
#include <cstdint>
#include <string_view>
#include <time.h>

#include <FEXCore/Utils/CompilerDefs.h>

Expand All @@ -14,14 +13,6 @@ FEX_DEFAULT_VISIBILITY void Shutdown();
FEX_DEFAULT_VISIBILITY void TraceObject(std::string_view const Format);
FEX_DEFAULT_VISIBILITY void TraceObject(std::string_view const Format, uint64_t Duration);

static inline uint64_t GetTime() {
// We want the time in the least amount of overhead possible
// clock_gettime will do a VDSO call with the least amount of overhead
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec * 1'000'000'000ULL + ts.tv_nsec;
}

// A class that follows scoping rules to generate a profile duration block
class ProfilerBlock final {
public:
Expand Down
3 changes: 3 additions & 0 deletions Source/Windows/ARM64EC/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ desc: Implements the ARM64EC BT module API using FEXCore
#include <FEXCore/Utils/Allocator.h>
#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/Threads.h>
#include <FEXCore/Utils/Profiler.h>
#include <FEXCore/Utils/EnumOperators.h>
#include <FEXCore/Utils/EnumUtils.h>
#include <FEXCore/Utils/FPState.h>
Expand Down Expand Up @@ -533,6 +534,8 @@ NTSTATUS ProcessInit() {
// Not applicable to Windows
FEXCore::Config::EraseSet(FEXCore::Config::ConfigOption::CONFIG_TSOAUTOMIGRATION, "0");

FEXCore::Profiler::Init();

FEXCore::Context::InitializeStaticTables(FEXCore::Context::MODE_64BIT);

SignalDelegator = fextl::make_unique<FEX::DummyHandlers::DummySignalDelegator>();
Expand Down
8 changes: 7 additions & 1 deletion Source/Windows/Common/CRT/IO.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,13 @@ DLLEXPORT_FUNC(int, _wopen, (const wchar_t* Filename, int OpenFlag, ...)) {
Attrs = FILE_ATTRIBUTE_READONLY;
}
}
HANDLE Handle = CreateFileW(Filename, OpenFlagToAccess(OpenFlag), FILE_SHARE_READ, nullptr, OpenFlagToCreation(OpenFlag), Attrs, nullptr);
auto access = OpenFlagToAccess(OpenFlag);
ULONG sharing = FILE_SHARE_READ;
if (access == GENERIC_WRITE) {
sharing |= FILE_SHARE_WRITE;
}

HANDLE Handle = CreateFileW(Filename, access, sharing, nullptr, OpenFlagToCreation(OpenFlag), Attrs, nullptr);
if (Handle != INVALID_HANDLE_VALUE) {
return AllocateFile(std::make_unique<FILE>(Handle, -1, OpenFlag & _O_APPEND));
}
Expand Down
3 changes: 3 additions & 0 deletions Source/Windows/WOW64/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ desc: Implements the WOW64 BT module API using FEXCore
#include <FEXCore/Utils/Allocator.h>
#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/Threads.h>
#include <FEXCore/Utils/Profiler.h>
#include <FEXCore/Utils/EnumOperators.h>
#include <FEXCore/Utils/EnumUtils.h>
#include <FEXCore/Utils/FPState.h>
Expand Down Expand Up @@ -457,6 +458,8 @@ void BTCpuProcessInit() {
// Not applicable to Windows
FEXCore::Config::EraseSet(FEXCore::Config::ConfigOption::CONFIG_TSOAUTOMIGRATION, "0");

FEXCore::Profiler::Init();

FEXCore::Context::InitializeStaticTables(FEXCore::Context::MODE_32BIT);

SignalDelegator = fextl::make_unique<FEX::DummyHandlers::DummySignalDelegator>();
Expand Down

0 comments on commit 8e2b4a3

Please sign in to comment.