mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 16:21:02 +00:00
Implement _sys_lwmutex_unlock (SYS_SYNC_RETRY mode)
This commit is contained in:
parent
ad6b0ee122
commit
d4459af4b3
@ -176,7 +176,7 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
|
|||||||
BIND_FUNC(sys_semaphore_get_value), //114 (0x072)
|
BIND_FUNC(sys_semaphore_get_value), //114 (0x072)
|
||||||
BIND_FUNC(_sys_lwcond_signal), //115 (0x073)
|
BIND_FUNC(_sys_lwcond_signal), //115 (0x073)
|
||||||
BIND_FUNC(_sys_lwcond_signal_all), //116 (0x074)
|
BIND_FUNC(_sys_lwcond_signal_all), //116 (0x074)
|
||||||
null_func,//BIND_FUNC(sys_semaphore_...) //117 (0x075) // internal, used by sys_lwmutex_unlock
|
BIND_FUNC(_sys_lwmutex_unlock2), //117 (0x075)
|
||||||
BIND_FUNC(sys_event_flag_clear), //118 (0x076)
|
BIND_FUNC(sys_event_flag_clear), //118 (0x076)
|
||||||
null_func,//BIND_FUNC(sys_time_get_rtc) //119 (0x077) ROOT
|
null_func,//BIND_FUNC(sys_time_get_rtc) //119 (0x077) ROOT
|
||||||
BIND_FUNC(sys_rwlock_create), //120 (0x078)
|
BIND_FUNC(sys_rwlock_create), //120 (0x078)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "Emu/Memory/vm.h"
|
#include "Emu/Memory/vm.h"
|
||||||
#include "Emu/System.h"
|
#include "Emu/System.h"
|
||||||
#include "Emu/IdManager.h"
|
#include "Emu/IdManager.h"
|
||||||
@ -73,17 +73,35 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
|
|||||||
{
|
{
|
||||||
sys_lwmutex.trace("_sys_lwmutex_lock(lwmutex_id=0x%x, timeout=0x%llx)", lwmutex_id, timeout);
|
sys_lwmutex.trace("_sys_lwmutex_lock(lwmutex_id=0x%x, timeout=0x%llx)", lwmutex_id, timeout);
|
||||||
|
|
||||||
|
ppu.gpr[3] = CELL_OK;
|
||||||
|
|
||||||
const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id, [&](lv2_lwmutex& mutex)
|
const auto mutex = idm::get<lv2_obj, lv2_lwmutex>(lwmutex_id, [&](lv2_lwmutex& mutex)
|
||||||
{
|
{
|
||||||
if (mutex.signaled.try_dec())
|
if (mutex.signaled.try_dec(0))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard lock(mutex.mutex);
|
std::lock_guard lock(mutex.mutex);
|
||||||
|
|
||||||
if (mutex.signaled.try_dec())
|
auto [old, _] = mutex.signaled.fetch_op([](s32& value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (old)
|
||||||
{
|
{
|
||||||
|
if (old == (1 << 31))
|
||||||
|
{
|
||||||
|
ppu.gpr[3] = CELL_EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,11 +117,9 @@ error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout)
|
|||||||
|
|
||||||
if (mutex.ret)
|
if (mutex.ret)
|
||||||
{
|
{
|
||||||
return CELL_OK;
|
return not_an_error(ppu.gpr[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu.gpr[3] = CELL_OK;
|
|
||||||
|
|
||||||
while (!ppu.state.test_and_reset(cpu_flag::signal))
|
while (!ppu.state.test_and_reset(cpu_flag::signal))
|
||||||
{
|
{
|
||||||
if (ppu.is_stopped())
|
if (ppu.is_stopped())
|
||||||
@ -146,7 +162,18 @@ error_code _sys_lwmutex_trylock(u32 lwmutex_id)
|
|||||||
|
|
||||||
const auto mutex = idm::check<lv2_obj, lv2_lwmutex>(lwmutex_id, [&](lv2_lwmutex& mutex)
|
const auto mutex = idm::check<lv2_obj, lv2_lwmutex>(lwmutex_id, [&](lv2_lwmutex& mutex)
|
||||||
{
|
{
|
||||||
return mutex.signaled.try_dec();
|
auto [_, ok] = mutex.signaled.fetch_op([](s32& value)
|
||||||
|
{
|
||||||
|
if (value & 1)
|
||||||
|
{
|
||||||
|
value = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return ok;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!mutex)
|
if (!mutex)
|
||||||
@ -175,7 +202,38 @@ error_code _sys_lwmutex_unlock(ppu_thread& ppu, u32 lwmutex_id)
|
|||||||
return cpu;
|
return cpu;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex.signaled.release(1);
|
mutex.signaled |= 1;
|
||||||
|
return nullptr;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!mutex)
|
||||||
|
{
|
||||||
|
return CELL_ESRCH;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mutex.ret)
|
||||||
|
{
|
||||||
|
mutex->awake(*mutex.ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
error_code _sys_lwmutex_unlock2(u32 lwmutex_id)
|
||||||
|
{
|
||||||
|
sys_lwmutex.warning("_sys_lwmutex_unlock2(lwmutex_id=0x%x)", lwmutex_id);
|
||||||
|
|
||||||
|
const auto mutex = idm::check<lv2_obj, lv2_lwmutex>(lwmutex_id, [&](lv2_lwmutex& mutex) -> cpu_thread*
|
||||||
|
{
|
||||||
|
std::lock_guard lock(mutex.mutex);
|
||||||
|
|
||||||
|
if (const auto cpu = mutex.schedule<ppu_thread>(mutex.sq, mutex.protocol))
|
||||||
|
{
|
||||||
|
static_cast<ppu_thread*>(cpu)->gpr[3] = CELL_EBUSY;
|
||||||
|
return cpu;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex.signaled |= 1 << 31;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ struct lv2_lwmutex final : lv2_obj
|
|||||||
const u64 name;
|
const u64 name;
|
||||||
|
|
||||||
shared_mutex mutex;
|
shared_mutex mutex;
|
||||||
atomic_t<u32> signaled{0};
|
atomic_t<s32> signaled{0};
|
||||||
std::deque<cpu_thread*> sq;
|
std::deque<cpu_thread*> sq;
|
||||||
|
|
||||||
lv2_lwmutex(u32 protocol, vm::ptr<sys_lwmutex_t> control, u64 name)
|
lv2_lwmutex(u32 protocol, vm::ptr<sys_lwmutex_t> control, u64 name)
|
||||||
@ -79,3 +79,4 @@ error_code _sys_lwmutex_destroy(u32 lwmutex_id);
|
|||||||
error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout);
|
error_code _sys_lwmutex_lock(ppu_thread& ppu, u32 lwmutex_id, u64 timeout);
|
||||||
error_code _sys_lwmutex_trylock(u32 lwmutex_id);
|
error_code _sys_lwmutex_trylock(u32 lwmutex_id);
|
||||||
error_code _sys_lwmutex_unlock(ppu_thread& ppu, u32 lwmutex_id);
|
error_code _sys_lwmutex_unlock(ppu_thread& ppu, u32 lwmutex_id);
|
||||||
|
error_code _sys_lwmutex_unlock2(u32 lwmutex_id);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user