mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-14 18:58:36 +12:00
sys_lwcond/cond/ppu_thread: Respect scheduler in various syscalls
This commit is contained in:
parent
5d4e87373f
commit
d152537e50
3 changed files with 402 additions and 202 deletions
|
@ -143,12 +143,31 @@ error_code sys_cond_signal(ppu_thread& ppu, u32 cond_id)
|
|||
|
||||
sys_cond.trace("sys_cond_signal(cond_id=0x%x)", cond_id);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ppu.test_stopped())
|
||||
{
|
||||
ppu.state += cpu_flag::again;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool finished = true;
|
||||
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
const auto cond = idm::check<lv2_obj, lv2_cond>(cond_id, [&, notify = lv2_obj::notify_all_t()](lv2_cond& cond)
|
||||
{
|
||||
if (atomic_storage<ppu_thread*>::load(cond.sq))
|
||||
{
|
||||
std::lock_guard lock(cond.mutex->mutex);
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
// Test if another signal caused the current thread to be suspended, in which case it needs to wait until the thread wakes up (otherwise the signal may cause unexpected results)
|
||||
finished = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (const auto cpu = cond.schedule<ppu_thread>(cond.sq, cond.mutex->protocol))
|
||||
{
|
||||
if (static_cast<ppu_thread*>(cpu)->state & cpu_flag::again)
|
||||
|
@ -165,14 +184,29 @@ error_code sys_cond_signal(ppu_thread& ppu, u32 cond_id)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cond.mutex->mutex.lock_unlock();
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
finished = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!finished)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cond)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
|
||||
|
@ -181,12 +215,31 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
|
|||
|
||||
sys_cond.trace("sys_cond_signal_all(cond_id=0x%x)", cond_id);
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ppu.test_stopped())
|
||||
{
|
||||
ppu.state += cpu_flag::again;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool finished = true;
|
||||
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
const auto cond = idm::check<lv2_obj, lv2_cond>(cond_id, [&, notify = lv2_obj::notify_all_t()](lv2_cond& cond)
|
||||
{
|
||||
if (atomic_storage<ppu_thread*>::load(cond.sq))
|
||||
{
|
||||
std::lock_guard lock(cond.mutex->mutex);
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
// Test if another signal caused the current thread to be suspended, in which case it needs to wait until the thread wakes up (otherwise the signal may cause unexpected results)
|
||||
finished = false;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto cpu = +cond.sq; cpu; cpu = cpu->next_cpu)
|
||||
{
|
||||
if (cpu->state & cpu_flag::again)
|
||||
|
@ -213,14 +266,29 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
|
|||
cond.awake(result);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cond.mutex->mutex.lock_unlock();
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
finished = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!finished)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cond)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
|
||||
|
@ -229,7 +297,19 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
|
|||
|
||||
sys_cond.trace("sys_cond_signal_to(cond_id=0x%x, thread_id=0x%x)", cond_id, thread_id);
|
||||
|
||||
const auto cond = idm::check<lv2_obj, lv2_cond>(cond_id, [&, notify = lv2_obj::notify_all_t()](lv2_cond& cond) -> int
|
||||
while (true)
|
||||
{
|
||||
if (ppu.test_stopped())
|
||||
{
|
||||
ppu.state += cpu_flag::again;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool finished = true;
|
||||
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
const auto cond = idm::check<lv2_obj, lv2_cond>(cond_id, [&, notify = lv2_obj::notify_all_t()](lv2_cond& cond)
|
||||
{
|
||||
if (!idm::check_unlocked<named_thread<ppu_thread>>(thread_id))
|
||||
{
|
||||
|
@ -240,6 +320,13 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
|
|||
{
|
||||
std::lock_guard lock(cond.mutex->mutex);
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
// Test if another signal caused the current thread to be suspended, in which case it needs to wait until the thread wakes up (otherwise the signal may cause unexpected results)
|
||||
finished = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (auto cpu = +cond.sq; cpu; cpu = cpu->next_cpu)
|
||||
{
|
||||
if (cpu->id == thread_id)
|
||||
|
@ -261,10 +348,25 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
|
|||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cond.mutex->mutex.lock_unlock();
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
finished = false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (!finished)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cond || cond.ret == -1)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -276,6 +378,7 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
|
|||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout)
|
||||
|
|
|
@ -155,6 +155,18 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
|||
fmt::throw_exception("Unknown mode (%d)", mode);
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (ppu.test_stopped())
|
||||
{
|
||||
ppu.state += cpu_flag::again;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool finished = true;
|
||||
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
const auto cond = idm::check<lv2_obj, lv2_lwcond>(lwcond_id, [&, notify = lv2_obj::notify_all_t()](lv2_lwcond& cond) -> int
|
||||
{
|
||||
ppu_thread* cpu = nullptr;
|
||||
|
@ -185,6 +197,13 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
|||
{
|
||||
std::lock_guard lock(cond.mutex);
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
// Test if another signal caused the current thread to be suspended, in which case it needs to wait until the thread wakes up (otherwise the signal may cause unexpected results)
|
||||
finished = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cpu)
|
||||
{
|
||||
if (static_cast<ppu_thread*>(cpu)->state & cpu_flag::again)
|
||||
|
@ -209,10 +228,7 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
|||
{
|
||||
static_cast<ppu_thread*>(result)->gpr[3] = CELL_EBUSY;
|
||||
}
|
||||
|
||||
if (mode != 2)
|
||||
{
|
||||
if (mode == 3 && mutex->load_sq()) [[unlikely]]
|
||||
else if (mode == 3 && mutex->load_sq()) [[unlikely]]
|
||||
{
|
||||
std::lock_guard lock(mutex->mutex);
|
||||
|
||||
|
@ -237,7 +253,6 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
|||
mutex->try_own(result, true);
|
||||
result = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
{
|
||||
|
@ -247,10 +262,25 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cond.mutex.lock_unlock();
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
finished = false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (!finished)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cond || cond.ret == -1)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -274,6 +304,7 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
|||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u32 mode)
|
||||
|
@ -290,7 +321,19 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
|
|||
fmt::throw_exception("Unknown mode (%d)", mode);
|
||||
}
|
||||
|
||||
const auto cond = idm::check<lv2_obj, lv2_lwcond>(lwcond_id, [&, notify = lv2_obj::notify_all_t()](lv2_lwcond& cond) -> s32
|
||||
while (true)
|
||||
{
|
||||
if (ppu.test_stopped())
|
||||
{
|
||||
ppu.state += cpu_flag::again;
|
||||
return {};
|
||||
}
|
||||
|
||||
bool finished = true;
|
||||
|
||||
ppu.state += cpu_flag::wait;
|
||||
|
||||
const auto cond = idm::check<lv2_obj, lv2_lwcond>(lwcond_id, [&, notify = lv2_obj::notify_all_t()](lv2_lwcond& cond) -> int
|
||||
{
|
||||
lv2_lwmutex* mutex{};
|
||||
|
||||
|
@ -308,6 +351,13 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
|
|||
{
|
||||
std::lock_guard lock(cond.mutex);
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
// Test if another signal caused the current thread to be suspended, in which case it needs to wait until the thread wakes up (otherwise the signal may cause unexpected results)
|
||||
finished = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 result = 0;
|
||||
|
||||
for (auto cpu = +cond.sq; cpu; cpu = cpu->next_cpu)
|
||||
|
@ -348,10 +398,25 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
|
|||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
cond.mutex.lock_unlock();
|
||||
|
||||
if (ppu.state & cpu_flag::suspend)
|
||||
{
|
||||
finished = false;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
if (!finished)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!cond || cond.ret == -1)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -364,6 +429,7 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
|
|||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u64 timeout)
|
||||
|
|
|
@ -338,22 +338,50 @@ error_code sys_ppu_thread_get_priority(ppu_thread& ppu, u32 thread_id, vm::ptr<s
|
|||
ppu.state += cpu_flag::wait;
|
||||
|
||||
sys_ppu_thread.trace("sys_ppu_thread_get_priority(thread_id=0x%x, priop=*0x%x)", thread_id, priop);
|
||||
u32 prio{};
|
||||
|
||||
if (thread_id == ppu.id)
|
||||
{
|
||||
// Fast path for self
|
||||
for (; !ppu.is_stopped(); std::this_thread::yield())
|
||||
{
|
||||
if (reader_lock lock(lv2_obj::g_mutex); cpu_flag::suspend - ppu.state)
|
||||
{
|
||||
prio = ppu.prio.load().prio;
|
||||
break;
|
||||
}
|
||||
|
||||
ppu.check_state();
|
||||
*priop = ppu.prio.load().prio;
|
||||
ppu.state += cpu_flag::wait;
|
||||
}
|
||||
|
||||
ppu.check_state();
|
||||
*priop = prio;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
u32 prio{};
|
||||
|
||||
for (; !ppu.is_stopped(); std::this_thread::yield())
|
||||
{
|
||||
bool check_state = false;
|
||||
const auto thread = idm::check<named_thread<ppu_thread>>(thread_id, [&](ppu_thread& thread)
|
||||
{
|
||||
if (reader_lock lock(lv2_obj::g_mutex); cpu_flag::suspend - ppu.state)
|
||||
{
|
||||
prio = thread.prio.load().prio;
|
||||
}
|
||||
else
|
||||
{
|
||||
check_state = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (check_state)
|
||||
{
|
||||
ppu.check_state();
|
||||
ppu.state += cpu_flag::wait;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!thread)
|
||||
{
|
||||
return CELL_ESRCH;
|
||||
|
@ -361,6 +389,9 @@ error_code sys_ppu_thread_get_priority(ppu_thread& ppu, u32 thread_id, vm::ptr<s
|
|||
|
||||
ppu.check_state();
|
||||
*priop = prio;
|
||||
break;
|
||||
}
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue