mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-15 03:08: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);
|
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)
|
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))
|
if (atomic_storage<ppu_thread*>::load(cond.sq))
|
||||||
{
|
{
|
||||||
std::lock_guard lock(cond.mutex->mutex);
|
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 (const auto cpu = cond.schedule<ppu_thread>(cond.sq, cond.mutex->protocol))
|
||||||
{
|
{
|
||||||
if (static_cast<ppu_thread*>(cpu)->state & cpu_flag::again)
|
if (static_cast<ppu_thread*>(cpu)->state & cpu_flag::again)
|
||||||
|
@ -165,8 +184,22 @@ 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)
|
if (!cond)
|
||||||
{
|
{
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
|
@ -174,6 +207,7 @@ error_code sys_cond_signal(ppu_thread& ppu, u32 cond_id)
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
|
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);
|
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)
|
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))
|
if (atomic_storage<ppu_thread*>::load(cond.sq))
|
||||||
{
|
{
|
||||||
std::lock_guard lock(cond.mutex->mutex);
|
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)
|
for (auto cpu = +cond.sq; cpu; cpu = cpu->next_cpu)
|
||||||
{
|
{
|
||||||
if (cpu->state & cpu_flag::again)
|
if (cpu->state & cpu_flag::again)
|
||||||
|
@ -213,8 +266,22 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
|
||||||
cond.awake(result);
|
cond.awake(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cond.mutex->mutex.lock_unlock();
|
||||||
|
|
||||||
|
if (ppu.state & cpu_flag::suspend)
|
||||||
|
{
|
||||||
|
finished = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!finished)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cond)
|
if (!cond)
|
||||||
{
|
{
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
|
@ -222,6 +289,7 @@ error_code sys_cond_signal_all(ppu_thread& ppu, u32 cond_id)
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
|
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);
|
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))
|
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);
|
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)
|
for (auto cpu = +cond.sq; cpu; cpu = cpu->next_cpu)
|
||||||
{
|
{
|
||||||
if (cpu->id == thread_id)
|
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;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!finished)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cond || cond.ret == -1)
|
if (!cond || cond.ret == -1)
|
||||||
{
|
{
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
|
@ -277,6 +379,7 @@ error_code sys_cond_signal_to(ppu_thread& ppu, u32 cond_id, u32 thread_id)
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error_code sys_cond_wait(ppu_thread& ppu, u32 cond_id, u64 timeout)
|
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);
|
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
|
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;
|
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);
|
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 (cpu)
|
||||||
{
|
{
|
||||||
if (static_cast<ppu_thread*>(cpu)->state & cpu_flag::again)
|
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;
|
static_cast<ppu_thread*>(result)->gpr[3] = CELL_EBUSY;
|
||||||
}
|
}
|
||||||
|
else if (mode == 3 && mutex->load_sq()) [[unlikely]]
|
||||||
if (mode != 2)
|
|
||||||
{
|
|
||||||
if (mode == 3 && mutex->load_sq()) [[unlikely]]
|
|
||||||
{
|
{
|
||||||
std::lock_guard lock(mutex->mutex);
|
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);
|
mutex->try_own(result, true);
|
||||||
result = nullptr;
|
result = nullptr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
|
@ -247,10 +262,25 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cond.mutex.lock_unlock();
|
||||||
|
|
||||||
|
if (ppu.state & cpu_flag::suspend)
|
||||||
|
{
|
||||||
|
finished = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!finished)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cond || cond.ret == -1)
|
if (!cond || cond.ret == -1)
|
||||||
{
|
{
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
|
@ -275,6 +305,7 @@ error_code _sys_lwcond_signal(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u6
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u32 mode)
|
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);
|
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{};
|
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);
|
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;
|
u32 result = 0;
|
||||||
|
|
||||||
for (auto cpu = +cond.sq; cpu; cpu = cpu->next_cpu)
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cond.mutex.lock_unlock();
|
||||||
|
|
||||||
|
if (ppu.state & cpu_flag::suspend)
|
||||||
|
{
|
||||||
|
finished = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!finished)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!cond || cond.ret == -1)
|
if (!cond || cond.ret == -1)
|
||||||
{
|
{
|
||||||
return CELL_ESRCH;
|
return CELL_ESRCH;
|
||||||
|
@ -365,6 +430,7 @@ error_code _sys_lwcond_signal_all(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
error_code _sys_lwcond_queue_wait(ppu_thread& ppu, u32 lwcond_id, u32 lwmutex_id, u64 timeout)
|
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;
|
ppu.state += cpu_flag::wait;
|
||||||
|
|
||||||
sys_ppu_thread.trace("sys_ppu_thread_get_priority(thread_id=0x%x, priop=*0x%x)", thread_id, priop);
|
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)
|
if (thread_id == ppu.id)
|
||||||
{
|
{
|
||||||
// Fast path for self
|
// 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();
|
ppu.check_state();
|
||||||
*priop = ppu.prio.load().prio;
|
ppu.state += cpu_flag::wait;
|
||||||
|
}
|
||||||
|
|
||||||
|
ppu.check_state();
|
||||||
|
*priop = prio;
|
||||||
return CELL_OK;
|
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)
|
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;
|
prio = thread.prio.load().prio;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
check_state = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (check_state)
|
||||||
|
{
|
||||||
|
ppu.check_state();
|
||||||
|
ppu.state += cpu_flag::wait;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!thread)
|
if (!thread)
|
||||||
{
|
{
|
||||||
return CELL_ESRCH;
|
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();
|
ppu.check_state();
|
||||||
*priop = prio;
|
*priop = prio;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue