Skip to content

Commit

Permalink
Merge pull request #1196 from Sonicadvance1/offline_telemetry
Browse files Browse the repository at this point in the history
Implements support for offline *only* telemetry
  • Loading branch information
Sonicadvance1 authored Aug 7, 2021
2 parents 5d73ac3 + c6c9457 commit b120a8e
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 46 deletions.
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ option(ENABLE_STRICT_WERROR "Enables stricter -Werror for CI" FALSE)
option(ENABLE_WERROR "Enables -Werror" FALSE)
option(ENABLE_STATIC_PIE "Enables static-pie build" FALSE)
option(ENABLE_JEMALLOC "Enables jemalloc allocator" TRUE)
option(ENABLE_OFFLINE_TELEMETRY "Enables FEX offline telemetry" TRUE)

set (X86_C_COMPILER "x86_64-linux-gnu-gcc" CACHE STRING "c compiler for compiling x86 guest libs")
set (X86_CXX_COMPILER "x86_64-linux-gnu-g++" CACHE STRING "c++ compiler for compiling x86 guest libs")
Expand Down Expand Up @@ -82,6 +83,11 @@ if (ENABLE_LLD)
link_libraries(${LD_OVERRIDE})
endif()

if (NOT ENABLE_OFFLINE_TELEMETRY)
# Disable FEX offline telemetry entirely if asked
add_definitions(-DFEX_DISABLE_TELEMETRY=1)
endif()

if (ENABLE_STATIC_PIE)
if (_M_ARM_64 AND ENABLE_LLD)
message (FATAL_ERROR "Static linking does not currently work with AArch64+LLD. Use GNU ld for now.")
Expand Down
1 change: 1 addition & 0 deletions External/FEXCore/Source/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ set (SRCS
Utils/Allocator.cpp
Utils/Allocator/64BitAllocator.cpp
Utils/LogManager.cpp
Utils/Telemetry.cpp
Utils/Threads.cpp
)

Expand Down
31 changes: 31 additions & 0 deletions External/FEXCore/Source/Common/Paths.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,43 @@

#include <cstdlib>
#include <filesystem>
#include <pwd.h>
#include <sys/stat.h>
#include <unistd.h>

namespace FEXCore::Paths {
std::unique_ptr<std::string> CachePath;
std::unique_ptr<std::string> EntryCache;

char const* FindUserHomeThroughUID() {
auto passwd = getpwuid(geteuid());
if (passwd) {
return passwd->pw_dir;
}
return nullptr;
}

const char *GetHomeDirectory() {
char const *HomeDir = getenv("HOME");

// Try to get home directory from uid
if (!HomeDir) {
HomeDir = FindUserHomeThroughUID();
}

// try the PWD
if (!HomeDir) {
HomeDir = getenv("PWD");
}

// Still doesn't exit? You get local
if (!HomeDir) {
HomeDir = ".";
}

return HomeDir;
}

void InitializePaths() {
CachePath = std::make_unique<std::string>();
EntryCache = std::make_unique<std::string>();
Expand Down
3 changes: 3 additions & 0 deletions External/FEXCore/Source/Common/Paths.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
namespace FEXCore::Paths {
void InitializePaths();
void ShutdownPaths();

const char *GetHomeDirectory();

std::string GetCachePath();
std::string GetEntryCachePath();
}
58 changes: 14 additions & 44 deletions External/FEXCore/Source/Interface/Config/Config.cpp
Original file line number Diff line number Diff line change
@@ -1,43 +1,30 @@
#include "Common/StringConv.h"
#include "Common/Paths.h"

#include <FEXCore/Utils/LogManager.h>
#include "Interface/Context/Context.h"

#include <FEXCore/Config/Config.h>
#include <filesystem>
#include <pwd.h>
#include <map>
#include <sys/sysinfo.h>
#include <unistd.h>

namespace FEXCore::Config {
char const* FindUserHomeThroughUID() {
auto passwd = getpwuid(geteuid());
if (passwd) {
return passwd->pw_dir;
}
return nullptr;
}

const char *GetHomeDirectory() {
char const *HomeDir = getenv("HOME");

// Try to get home directory from uid
if (!HomeDir) {
HomeDir = FindUserHomeThroughUID();
}
std::string GetDataDirectory() {
std::string DataDir{};

// try the PWD
if (!HomeDir) {
HomeDir = getenv("PWD");
char const *HomeDir = Paths::GetHomeDirectory();
char const *DataXDG = getenv("XDG_DATA_HOME");
char const *DataOverride = getenv("FEX_APP_DATA_LOCATION");
if (DataOverride) {
// Data override will override the complete directory
DataDir = DataOverride;
}

// Still doesn't exit? You get local
if (!HomeDir) {
HomeDir = ".";
else {
DataDir = DataXDG ?: HomeDir;
DataDir += "/.fex-emu/";
}

return HomeDir;
return DataDir;
}

std::string GetConfigDirectory(bool Global) {
Expand All @@ -46,7 +33,7 @@ namespace FEXCore::Config {
ConfigDir = GLOBAL_DATA_DIRECTORY;
}
else {
char const *HomeDir = GetHomeDirectory();
char const *HomeDir = Paths::GetHomeDirectory();
char const *ConfigXDG = getenv("XDG_CONFIG_HOME");
char const *ConfigOverride = getenv("FEX_APP_CONFIG_LOCATION");
if (ConfigOverride) {
Expand Down Expand Up @@ -109,23 +96,6 @@ namespace FEXCore::Config {
return ConfigFile;
}

std::string GetDataDirectory() {
std::string DataDir{};

char const *HomeDir = GetHomeDirectory();
char const *DataXDG = getenv("XDG_DATA_HOME");
char const *DataOverride = getenv("FEX_APP_DATA_LOCATION");
if (DataOverride) {
// Data override will override the complete directory
DataDir = DataOverride;
}
else {
DataDir = DataXDG ?: HomeDir;
DataDir += "/.fex-emu/";
}
return DataDir;
}

void SetConfig(FEXCore::Context::Context *CTX, ConfigOption Option, uint64_t Config) {
}

Expand Down
32 changes: 32 additions & 0 deletions External/FEXCore/Source/Interface/Core/ArchHelpers/Arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
#include "Interface/Core/ArchHelpers/MContext.h"

#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/Telemetry.h>

#include <atomic>
#include <stdint.h>

#include <signal.h>

namespace FEXCore::ArchHelpers::Arm64 {
FEXCORE_TELEMETRY_STATIC_INIT(SplitLock, TYPE_HAS_SPLIT_LOCKS);
FEXCORE_TELEMETRY_STATIC_INIT(SplitLock16B, TYPE_16BYTE_SPLIT);

static __uint128_t LoadAcquire128(uint64_t Addr) {
__uint128_t Result{};
uint64_t Lower;
Expand Down Expand Up @@ -94,8 +98,15 @@ bool HandleCASPAL(void *_ucontext, void *_info, uint32_t Instr) {
// Both cross-cacheline and cross 16byte both need dual CAS loops that can tear
// ARMv8.4 LSE2 solves all atomic issues except cross-cacheline

// Check for Split lock across a cacheline
if ((Addr & 63) > 56) {
FEXCORE_TELEMETRY_SET(SplitLock, 1);
}

uint64_t AlignmentMask = 0b1111;
if ((Addr & AlignmentMask) > 8) {
FEXCORE_TELEMETRY_SET(SplitLock16B, 1);

uint64_t Alignment = Addr & 0b111;
Addr &= ~0b111ULL;
uint64_t AddrUpper = Addr + 8;
Expand Down Expand Up @@ -430,9 +441,16 @@ uint16_t DoCAS16(
uint64_t Addr,
CASExpectedFn<uint16_t> ExpectedFunction,
CASDesiredFn<uint16_t> DesiredFunction) {

if ((Addr & 63) == 63) {
FEXCORE_TELEMETRY_SET(SplitLock, 1);
}

// 16 bit
uint64_t AlignmentMask = 0b1111;
if ((Addr & AlignmentMask) == 15) {
FEXCORE_TELEMETRY_SET(SplitLock16B, 1);

// Address crosses over 16byte or 64byte threshold
// Need a dual 8bit CAS loop
uint64_t AddrUpper = Addr + 1;
Expand Down Expand Up @@ -706,9 +724,16 @@ uint32_t DoCAS32(
uint64_t Addr,
CASExpectedFn<uint32_t> ExpectedFunction,
CASDesiredFn<uint32_t> DesiredFunction) {

if ((Addr & 63) > 60) {
FEXCORE_TELEMETRY_SET(SplitLock, 1);
}

// 32 bit
uint64_t AlignmentMask = 0b1111;
if ((Addr & AlignmentMask) > 12) {
FEXCORE_TELEMETRY_SET(SplitLock16B, 1);

// Address crosses over 16byte threshold
// Needs dual 4 byte CAS loop
uint64_t Alignment = Addr & 0b11;
Expand Down Expand Up @@ -936,9 +961,16 @@ uint64_t DoCAS64(
uint64_t Addr,
CASExpectedFn<uint64_t> ExpectedFunction,
CASDesiredFn<uint64_t> DesiredFunction) {

if ((Addr & 63) > 56) {
FEXCORE_TELEMETRY_SET(SplitLock, 1);
}

// 64bit
uint64_t AlignmentMask = 0b1111;
if ((Addr & AlignmentMask) > 8) {
FEXCORE_TELEMETRY_SET(SplitLock16B, 1);

uint64_t Alignment = Addr & 0b111;
Addr &= ~0b111ULL;
uint64_t AddrUpper = Addr + 8;
Expand Down
4 changes: 3 additions & 1 deletion External/FEXCore/Source/Interface/Core/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,9 @@ namespace FEXCore::Context {

if (NewBlock == 0) {
LogMan::Msg::E("CompileBlockJit: Failed to compile code %lX - aborting process", GuestRIP);
abort();
// Return similar behaviour of SIGILL abort
Frame->Thread->StatusCode = 128 + SIGILL;
Stop(false /* Ignore current thread */);
}
}

Expand Down
5 changes: 5 additions & 0 deletions External/FEXCore/Source/Interface/Core/Frontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ desc: Extracts instruction & block meta info, frontend multiblock logic
#include <FEXCore/Core/X86Enums.h>
#include <FEXCore/Debug/X86Tables.h>
#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/Telemetry.h>
#include <set>
#include <sys/mman.h>

Expand Down Expand Up @@ -696,6 +697,7 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16
return NormalOp(&X87Ops[X87Op], X87Op);
}
else if (Info->Type == FEXCore::X86Tables::TYPE_VEX_TABLE_PREFIX) {
FEXCORE_TELEMETRY_SET(VEXOpTelem, 1);
uint16_t map_select = 1;
uint16_t pp = 0;

Expand Down Expand Up @@ -723,6 +725,7 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16

if (LocalInfo->Type >= FEXCore::X86Tables::TYPE_VEX_GROUP_12 &&
LocalInfo->Type <= FEXCore::X86Tables::TYPE_VEX_GROUP_17) {
FEXCORE_TELEMETRY_SET(VEXOpTelem, 1);
// We have ModRM
uint8_t ModRMByte = ReadByte();
DecodeInst->ModRM = ModRMByte;
Expand All @@ -740,6 +743,8 @@ bool Decoder::NormalOpHeader(FEXCore::X86Tables::X86InstInfo const *Info, uint16
return NormalOp(LocalInfo, Op);
}
else if (Info->Type == FEXCore::X86Tables::TYPE_GROUP_EVEX) {
FEXCORE_TELEMETRY_SET(EVEXOpTelem, 1);

/* uint8_t P1 = */ ReadByte();
/* uint8_t P2 = */ ReadByte();
/* uint8_t P3 = */ ReadByte();
Expand Down
4 changes: 4 additions & 0 deletions External/FEXCore/Source/Interface/Core/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <FEXCore/Debug/X86Tables.h>
#include <FEXCore/HLE/SyscallHandler.h>
#include <FEXCore/Utils/Telemetry.h>

#include <array>
#include <cstdint>
Expand Down Expand Up @@ -89,5 +90,8 @@ class Decoder final {
};

const uint8_t *AdjustAddrForSpecialRegion(uint8_t const* _InstStream, uint64_t EntryPoint, uint64_t RIP);

FEXCORE_TELEMETRY_INIT(VEXOpTelem, TYPE_USES_VEX_OPS);
FEXCORE_TELEMETRY_INIT(EVEXOpTelem, TYPE_USES_EVEX_OPS);
};
}
61 changes: 61 additions & 0 deletions External/FEXCore/Source/Utils/Telemetry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@

#include "Common/Paths.h"

#include <FEXCore/Config/Config.h>
#include <FEXCore/Utils/LogManager.h>
#include <FEXCore/Utils/Telemetry.h>

#include <array>
#include <filesystem>
#include <fstream>

namespace FEXCore::Telemetry {
#ifndef FEX_DISABLE_TELEMETRY
static std::array<Value, FEXCore::Telemetry::TelemetryType::TYPE_LAST> TelemetryValues = {{ }};
const std::array<std::string, FEXCore::Telemetry::TelemetryType::TYPE_LAST> TelemetryNames {
"64byte Split Locks",
"16Byte Split atomics",
"VEX instructions (AVX)",
"EVEX instructions (AVX512)",
};
void Initialize() {
auto DataDirectory = Config::GetDataDirectory();
DataDirectory += "Telemetry/";

// Ensure the folder structure is created for our configuration
std::error_code ec{};
if (!std::filesystem::exists(DataDirectory, ec) &&
!std::filesystem::create_directories(DataDirectory, ec)) {
LogMan::Msg::I("Couldn't create telemetry Folder");
}
}

void Shutdown(std::filesystem::path &ApplicationName) {
auto DataDirectory = Config::GetDataDirectory();
DataDirectory += "Telemetry/" + ApplicationName.string() + ".telem";

std::error_code ec{};
if (std::filesystem::exists(DataDirectory, ec)) {
// If the file exists, retain a single backup
auto Backup = DataDirectory + ".1";
std::filesystem::copy_file(DataDirectory, Backup, std::filesystem::copy_options::overwrite_existing, ec);
}

std::fstream fs(DataDirectory, std::ios_base::out | std::ios_base::trunc);
if (fs.is_open()) {
for (size_t i = 0; i < TelemetryType::TYPE_LAST; ++i) {
auto &Name = TelemetryNames.at(i);
auto &Data = TelemetryValues.at(i);
fs << Name << ": " << *Data << std::endl;
}

fs.flush();
fs.close();
}
}

Value &GetObject(TelemetryType Type) {
return TelemetryValues.at(Type);
}
#endif
}
Loading

0 comments on commit b120a8e

Please sign in to comment.