Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixups #8117

Merged
merged 3 commits into from
Apr 28, 2020
Merged

Fixups #8117

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
62 changes: 61 additions & 1 deletion Utilities/Thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2431,6 +2431,66 @@ void thread_ctrl::set_thread_affinity_mask(u64 mask)
}
}

pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs);
if (int err = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs))
{
sig_log.error("Failed to set thread affinity 0x%x: error %d.", mask, err);
}
#endif
}

u64 thread_ctrl::get_thread_affinity_mask()
{
#ifdef _WIN32
DWORD_PTR res, _sys;
if (!GetProcessAffinityMask(GetCurrentProcess(), &res, &_sys))
{
sig_log.error("Failed to get process affinity mask.");
return 0;
}

if (DWORD_PTR result = SetThreadAffinityMask(GetCurrentThread(), res))
{
if (res != result)
{
SetThreadAffinityMask(GetCurrentThread(), result);
}

return result;
}

sig_log.error("Failed to get thread affinity mask.");
return 0;
#elif defined(__linux__) || defined(__DragonFly__) || defined(__FreeBSD__)
cpu_set_t cs;
CPU_ZERO(&cs);

if (int err = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cs))
{
sig_log.error("Failed to get thread affinity mask: error %d.", err);
return 0;
}

u64 result;

for (u32 core = 0; core < 64u; core++)
{
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
if (CPU_ISSET(core, &cs))
#pragma GCC diagnostic pop
{
result |= 1ull << core;
}
}

if (result == 0)
{
sig_log.error("Thread affinity mask is out of u64 range.");
return 0;
}

return result;
#else
return -1;
#endif
}
3 changes: 3 additions & 0 deletions Utilities/Thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,9 @@ class thread_ctrl final

// Sets the preferred affinity mask for this thread
static void set_thread_affinity_mask(u64 mask);

// Miscellaneous
static u64 get_thread_affinity_mask();
};

// Derived from the callable object Context, possibly a lambda
Expand Down
30 changes: 21 additions & 9 deletions Utilities/sysinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include "StrFmt.h"
#include "File.h"
#include "Emu/system_config.h"
#include "Thread.h"

#ifdef _WIN32
#include "windows.h"
Expand Down Expand Up @@ -283,37 +284,48 @@ ullong utils::get_tsc_freq()
return round_tsc(freq.QuadPart * 1024);

const ullong timer_freq = freq.QuadPart;
Sleep(1);
#else
const ullong timer_freq = 1'000'000'000;
ullong sec_base = 0;
usleep(200);
#endif

// Calibrate TSC
constexpr int samples = 40;
ullong rdtsc_data[samples];
ullong timer_data[samples];
ullong error_data[samples];

// Narrow thread affinity to a single core
const u64 old_aff = thread_ctrl::get_thread_affinity_mask();
thread_ctrl::set_thread_affinity_mask(old_aff & (0 - old_aff));

#ifndef _WIN32
struct timespec ts0;
clock_gettime(CLOCK_MONOTONIC, &ts0);
ullong sec_base = ts0.tv_sec;
#endif

for (int i = 0; i < samples; i++)
{
rdtsc_data[i] = (_mm_lfence(), __rdtsc());

#ifdef _WIN32
Sleep(1);
error_data[i] = (_mm_lfence(), __rdtsc());
LARGE_INTEGER ctr;
QueryPerformanceCounter(&ctr);
rdtsc_data[i] = (_mm_lfence(), __rdtsc());
timer_data[i] = ctr.QuadPart;
Sleep(1);
#else
usleep(200);
error_data[i] = (_mm_lfence(), __rdtsc());
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
if (i == 0)
sec_base = ts.tv_sec;
rdtsc_data[i] = (_mm_lfence(), __rdtsc());
timer_data[i] = ts.tv_nsec + (ts.tv_sec - sec_base) * 1'000'000'000;
usleep(200);
#endif
}

// Restore main thread affinity
thread_ctrl::set_thread_affinity_mask(old_aff);

// Compute average TSC
ullong acc = 0;
for (int i = 0; i < samples - 1; i++)
Expand Down
2 changes: 0 additions & 2 deletions rpcs3/Emu/Cell/PPUThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1050,8 +1050,6 @@ static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr)

if ((vm::reservation_acquire(addr, sizeof(T)) & -128) == ppu.rtime) [[likely]]
{
ppu.test_stopped();

if (count >= 10) [[unlikely]]
{
ppu_log.error("%s took too long: %u", sizeof(T) == 4 ? "LWARX" : "LDARX", count);
Expand Down