[Threading] Improve same-CPU spinlock contention

Spinlock acquire now checks if the lock holder shares the same guest
CPU and yields more aggressively (Sleep(0)) when contending on the
same Xenon HW thread, which should better approximate real kernel's
implicit serialization.

Child threads without an explicit affinity mask now inherit the
parent's guest CPU assignment instead of round-robining, so the
spinlock check correctly identifies parent-child co-location.
This commit is contained in:
Herman S.
2026-04-09 21:14:39 +09:00
parent e23376afcc
commit 61c8eb0707
2 changed files with 37 additions and 10 deletions

View File

@@ -155,13 +155,17 @@ static uint8_t next_cpu = 0;
static uint8_t GetFakeCpuNumber(uint8_t proc_mask) {
// NOTE: proc_mask is logical processors, not physical processors or cores.
if (!proc_mask) {
next_cpu = (next_cpu + 1) % 6;
return next_cpu; // is this reasonable?
// TODO(Triang3l): Does the following apply here?
// On Xbox 360, threads without an explicit processor assignment stay on
// the same hardware thread as the parent. Preserve this so that the
// guest CPU assignment reflects the game's intent — parent-child thread
// pairs that share a HW thread may rely on implicit serialization.
// https://docs.microsoft.com/en-us/windows/win32/dxtecharts/coding-for-multiple-cores
// "On Xbox 360, you must explicitly assign software threads to a particular
// hardware thread by using XSetThreadProcessor. Otherwise, all child
// threads will stay on the same hardware thread as the parent."
XThread* parent = current_xthread_tls_;
if (parent) {
return parent->active_cpu();
}
next_cpu = (next_cpu + 1) % 6;
return next_cpu;
}
assert_false(proc_mask & 0xC0);