mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 07:20:59 +00:00
SPU: Use optimized PPU signaling to SPU on reservation pause
This commit is contained in:
parent
525453794f
commit
b38580bf32
@ -466,6 +466,7 @@ bool cpu_thread::check_state() noexcept
|
|||||||
|
|
||||||
bool cpu_sleep_called = false;
|
bool cpu_sleep_called = false;
|
||||||
bool cpu_flag_memory = false;
|
bool cpu_flag_memory = false;
|
||||||
|
bool escape, retval;
|
||||||
|
|
||||||
if (!(state & cpu_flag::wait))
|
if (!(state & cpu_flag::wait))
|
||||||
{
|
{
|
||||||
@ -474,54 +475,73 @@ bool cpu_thread::check_state() noexcept
|
|||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
if (state & cpu_flag::memory)
|
// Process all flags in a single atomic op
|
||||||
|
const auto state0 = state.fetch_op([&](bs_t<cpu_flag>& flags)
|
||||||
{
|
{
|
||||||
if (auto& ptr = vm::g_tls_locked)
|
bool store = false;
|
||||||
|
|
||||||
|
if (flags & cpu_flag::signal)
|
||||||
{
|
{
|
||||||
ptr->compare_and_swap(this, nullptr);
|
flags -= cpu_flag::signal;
|
||||||
ptr = nullptr;
|
cpu_sleep_called = false;
|
||||||
|
store = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_flag_memory = true;
|
|
||||||
state -= cpu_flag::memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state & (cpu_flag::exit + cpu_flag::dbg_global_stop))
|
|
||||||
{
|
|
||||||
state += cpu_flag::wait;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto [state0, escape] = state.fetch_op([&](bs_t<cpu_flag>& flags)
|
|
||||||
{
|
|
||||||
// Atomically clean wait flag and escape
|
// Atomically clean wait flag and escape
|
||||||
if (!(flags & (cpu_flag::exit + cpu_flag::dbg_global_stop + cpu_flag::ret + cpu_flag::stop)))
|
if (!(flags & (cpu_flag::exit + cpu_flag::dbg_global_stop + cpu_flag::ret + cpu_flag::stop)))
|
||||||
{
|
{
|
||||||
// Check pause flags which hold thread inside check_state
|
// Check pause flags which hold thread inside check_state
|
||||||
if (flags & (cpu_flag::pause + cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause))
|
if (flags & (cpu_flag::pause + cpu_flag::suspend + cpu_flag::dbg_global_pause + cpu_flag::dbg_pause))
|
||||||
{
|
{
|
||||||
return false;
|
escape = false;
|
||||||
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
flags -= cpu_flag::wait;
|
if (flags & cpu_flag::memory)
|
||||||
|
{
|
||||||
|
// wait flag will be cleared later (optimization)
|
||||||
|
cpu_flag_memory = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AUDIT(!cpu_flag_memory);
|
||||||
|
flags -= cpu_flag::wait;
|
||||||
|
store = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cpu_flag_memory = false;
|
||||||
|
retval = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
if (flags & cpu_flag::dbg_step)
|
||||||
});
|
{
|
||||||
|
flags += cpu_flag::dbg_pause;
|
||||||
|
flags -= cpu_flag::dbg_step;
|
||||||
|
store = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (state & cpu_flag::signal && state.test_and_reset(cpu_flag::signal))
|
escape = true;
|
||||||
{
|
return store;
|
||||||
cpu_sleep_called = false;
|
}).first;
|
||||||
}
|
|
||||||
|
|
||||||
if (escape)
|
if (escape)
|
||||||
{
|
{
|
||||||
if (cpu_flag_memory)
|
if (cpu_flag_memory)
|
||||||
{
|
{
|
||||||
cpu_mem();
|
cpu_mem();
|
||||||
|
|
||||||
|
if (state & (cpu_flag::pause + cpu_flag::memory)) [[unlikely]]
|
||||||
|
{
|
||||||
|
state += cpu_flag::wait;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
return retval;
|
||||||
}
|
}
|
||||||
else if (!cpu_sleep_called && state0 & cpu_flag::suspend)
|
else if (!cpu_sleep_called && state0 & cpu_flag::suspend)
|
||||||
{
|
{
|
||||||
@ -540,21 +560,6 @@ bool cpu_thread::check_state() noexcept
|
|||||||
g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_unlock();
|
g_fxo->get<cpu_counter>()->cpu_suspend_lock.lock_unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto state_ = state.load();
|
|
||||||
|
|
||||||
if (state_ & (cpu_flag::ret + cpu_flag::stop))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state_ & cpu_flag::dbg_step)
|
|
||||||
{
|
|
||||||
state += cpu_flag::dbg_pause;
|
|
||||||
state -= cpu_flag::dbg_step;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_thread::notify()
|
void cpu_thread::notify()
|
||||||
|
@ -129,9 +129,30 @@ namespace vm
|
|||||||
{
|
{
|
||||||
if (g_tls_locked && *g_tls_locked == &cpu) [[unlikely]]
|
if (g_tls_locked && *g_tls_locked == &cpu) [[unlikely]]
|
||||||
{
|
{
|
||||||
|
if (cpu.state & cpu_flag::wait)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
g_mutex.lock_unlock();
|
||||||
|
cpu.state -= cpu_flag::wait + cpu_flag::memory;
|
||||||
|
|
||||||
|
if (g_mutex.is_lockable()) [[likely]]
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cpu.state += cpu_flag::wait;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cpu.state & cpu_flag::memory)
|
||||||
|
{
|
||||||
|
cpu.state -= cpu_flag::memory;
|
||||||
|
}
|
||||||
|
|
||||||
if (g_mutex.is_lockable()) [[likely]]
|
if (g_mutex.is_lockable()) [[likely]]
|
||||||
{
|
{
|
||||||
// Optimistic path (hope that mutex is not exclusively locked)
|
// Optimistic path (hope that mutex is not exclusively locked)
|
||||||
@ -355,7 +376,8 @@ namespace vm
|
|||||||
|
|
||||||
for (auto lock = g_locks.cbegin(), end = lock + g_cfg.core.ppu_threads; lock != end; lock++)
|
for (auto lock = g_locks.cbegin(), end = lock + g_cfg.core.ppu_threads; lock != end; lock++)
|
||||||
{
|
{
|
||||||
while (*lock)
|
cpu_thread* ptr;
|
||||||
|
while ((ptr = *lock) && !(ptr->state & cpu_flag::wait))
|
||||||
{
|
{
|
||||||
_mm_pause();
|
_mm_pause();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user