Add yield() function to tell the CPU that we're busy-waiting (rare) (#17862)

* Add yield() function to tell the CPU that we're busy-waiting (rare)

Use it only for the busy-wait in lag sync, which only happens in
Windows.

* Buildfix attempt
This commit is contained in:
Henrik Rydgård 2023-08-07 21:38:03 +02:00 committed by GitHub
parent 1f3136155b
commit 096c168dd7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 2 deletions

View File

@ -17,6 +17,12 @@
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
// for _mm_pause
#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
#include <immintrin.h>
#endif
#include <ctime> #include <ctime>
// TODO: https://github.com/floooh/sokol/blob/9a6237fcdf213e6da48e4f9201f144bcb2dcb46f/sokol_time.h#L229-L248 // TODO: https://github.com/floooh/sokol/blob/9a6237fcdf213e6da48e4f9201f144bcb2dcb46f/sokol_time.h#L229-L248
@ -24,7 +30,7 @@
static const double micros = 1000000.0; static const double micros = 1000000.0;
static const double nanos = 1000000000.0; static const double nanos = 1000000000.0;
#ifdef _WIN32 #if PPSSPP_PLATFORM(WINDOWS)
static LARGE_INTEGER frequency; static LARGE_INTEGER frequency;
static double frequencyMult; static double frequencyMult;
@ -58,6 +64,10 @@ double from_time_raw_relative(uint64_t raw_time) {
return from_time_raw(raw_time); return from_time_raw(raw_time);
} }
void yield() {
YieldProcessor();
}
#elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS) #elif PPSSPP_PLATFORM(ANDROID) || PPSSPP_PLATFORM(LINUX) || PPSSPP_PLATFORM(MAC) || PPSSPP_PLATFORM(IOS)
// The only intended use is to match the timings in VK_GOOGLE_display_timing // The only intended use is to match the timings in VK_GOOGLE_display_timing
@ -85,6 +95,14 @@ double from_time_raw_relative(uint64_t raw_time) {
return (double)raw_time * (1.0 / nanos); return (double)raw_time * (1.0 / nanos);
} }
void yield() {
#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
_mm_pause();
#elif PPSSPP_ARCH(ARM64)
__builtin_arm_isb(15);
#endif
}
#else #else
double time_now_d() { double time_now_d() {
@ -110,6 +128,8 @@ double from_time_raw_relative(uint64_t raw_time) {
return from_time_raw(raw_time); return from_time_raw(raw_time);
} }
void yield() {}
#endif #endif
void sleep_ms(int ms) { void sleep_ms(int ms) {

View File

@ -16,6 +16,9 @@ double from_time_raw_relative(uint64_t raw_time);
// Sleep. Does not necessarily have millisecond granularity, especially on Windows. // Sleep. Does not necessarily have millisecond granularity, especially on Windows.
void sleep_ms(int ms); void sleep_ms(int ms);
// Yield. Signals that this thread is busy-waiting but wants to allow other hyperthreads to run.
void yield();
void GetTimeFormatted(char formattedTime[13]); void GetTimeFormatted(char formattedTime[13]);
// Rust-style Instant for clear and easy timing. // Rust-style Instant for clear and easy timing.

View File

@ -718,6 +718,8 @@ void hleLagSync(u64 userdata, int cyclesLate) {
#ifndef _WIN32 #ifndef _WIN32
const double left = goal - now; const double left = goal - now;
usleep((long)(left * 1000000.0)); usleep((long)(left * 1000000.0));
#else
yield();
#endif #endif
now = time_now_d(); now = time_now_d();
} }

View File

@ -898,7 +898,7 @@ static UI::AnchorLayoutParams *AnchorInCorner(const Bounds &bounds, int corner,
switch ((ScreenEdgePosition)g_Config.iChatButtonPosition) { switch ((ScreenEdgePosition)g_Config.iChatButtonPosition) {
case ScreenEdgePosition::BOTTOM_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, NONE, NONE, yOffset, true); case ScreenEdgePosition::BOTTOM_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, NONE, NONE, yOffset, true);
case ScreenEdgePosition::BOTTOM_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), NONE, NONE, yOffset, true); case ScreenEdgePosition::BOTTOM_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), NONE, NONE, yOffset, true);
case ScreenEdgePosition::BOTTOM_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, NONE, xOffset, yOffset, true); case ScreenEdgePosition::BOTTOM_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, NONE, xOffset, yOffset, true);
case ScreenEdgePosition::TOP_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, yOffset, NONE, NONE, true); case ScreenEdgePosition::TOP_LEFT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, xOffset, yOffset, NONE, NONE, true);
case ScreenEdgePosition::TOP_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), yOffset, NONE, NONE, true); case ScreenEdgePosition::TOP_CENTER: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, bounds.centerX(), yOffset, NONE, NONE, true);
case ScreenEdgePosition::TOP_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, yOffset, xOffset, NONE, true); case ScreenEdgePosition::TOP_RIGHT: return new AnchorLayoutParams(WRAP_CONTENT, WRAP_CONTENT, NONE, yOffset, xOffset, NONE, true);