mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-04 15:50:10 +01:00
[orbis-kernel] Implement umtx_wake_umutex
This commit is contained in:
parent
51150f4b07
commit
9a3054a5d1
|
|
@ -38,6 +38,8 @@ struct UmtxChain {
|
|||
|
||||
std::pair<const UmtxKey, UmtxCond> *enqueue(UmtxKey &key, Thread *thr);
|
||||
void erase(std::pair<const UmtxKey, UmtxCond> *obj);
|
||||
void notify_one(const UmtxKey &key);
|
||||
void notify_all(const UmtxKey &key);
|
||||
};
|
||||
|
||||
class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {
|
||||
|
|
|
|||
|
|
@ -86,8 +86,7 @@ ErrorCode umtx_wait_uint_private(Thread *thread, ptr<void> addr, ulong id,
|
|||
std::uint64_t ut);
|
||||
ErrorCode umtx_wake_private(Thread *thread, ptr<void> uaddr, sint n_wake);
|
||||
ErrorCode umtx_wait_umutex(Thread *thread, ptr<umutex> m, std::uint64_t ut);
|
||||
ErrorCode umtx_wake_umutex(Thread *thread, ptr<void> obj, std::int64_t val,
|
||||
ptr<void> uaddr1, ptr<void> uaddr2);
|
||||
ErrorCode umtx_wake_umutex(Thread *thread, ptr<umutex> m);
|
||||
ErrorCode umtx_sem_wait(Thread *thread, ptr<void> obj, std::int64_t val,
|
||||
ptr<void> uaddr1, ptr<void> uaddr2);
|
||||
ErrorCode umtx_sem_wake(Thread *thread, ptr<void> obj, std::int64_t val,
|
||||
|
|
|
|||
|
|
@ -15,13 +15,13 @@ static orbis::ErrorCode ureadTimespec(orbis::timespec &ts,
|
|||
}
|
||||
|
||||
orbis::SysResult orbis::sys__umtx_lock(Thread *thread, ptr<umtx> umtx) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, umtx);
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, umtx);
|
||||
if (reinterpret_cast<std::uintptr_t>(umtx) - 0x10000 > 0xff'fffe'ffff)
|
||||
return ErrorCode::FAULT;
|
||||
return umtx_lock_umtx(thread, umtx, thread->tid, -1);
|
||||
}
|
||||
orbis::SysResult orbis::sys__umtx_unlock(Thread *thread, ptr<umtx> umtx) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, umtx);
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, umtx);
|
||||
if (reinterpret_cast<std::uintptr_t>(umtx) - 0x10000 > 0xff'fffe'ffff)
|
||||
return ErrorCode::FAULT;
|
||||
return umtx_unlock_umtx(thread, umtx, thread->tid);
|
||||
|
|
@ -29,7 +29,7 @@ orbis::SysResult orbis::sys__umtx_unlock(Thread *thread, ptr<umtx> umtx) {
|
|||
orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
||||
ulong val, ptr<void> uaddr1,
|
||||
ptr<void> uaddr2) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, obj, op, val, uaddr1, uaddr2);
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, obj, op, val, uaddr1, uaddr2);
|
||||
if (reinterpret_cast<std::uintptr_t>(obj) - 0x10000 > 0xff'fffe'ffff)
|
||||
return ErrorCode::FAULT;
|
||||
auto with_timeout = [&](auto op) -> orbis::ErrorCode {
|
||||
|
|
@ -127,7 +127,7 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
});
|
||||
}
|
||||
case 18:
|
||||
return umtx_wake_umutex(thread, obj, val, uaddr1, uaddr2);
|
||||
return umtx_wake_umutex(thread, (ptr<umutex>)obj);
|
||||
case 19:
|
||||
return umtx_sem_wait(thread, obj, val, uaddr1, uaddr2);
|
||||
case 20:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,13 @@ void UmtxChain::erase(std::pair<const UmtxKey, UmtxCond> *obj) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UmtxChain::notify_one(const UmtxKey &key) {
|
||||
auto it = sleep_queue.find(key);
|
||||
it->second.thr = nullptr;
|
||||
it->second.cv.notify_one(mtx);
|
||||
this->erase(&*it);
|
||||
}
|
||||
} // namespace orbis
|
||||
|
||||
orbis::ErrorCode orbis::umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
|
||||
|
|
@ -145,10 +152,7 @@ static ErrorCode do_unlock_normal(Thread *thread, ptr<umutex> m, uint flags) {
|
|||
std::size_t count = chain.sleep_queue.count(key);
|
||||
bool ok = m->owner.compare_exchange_strong(
|
||||
owner, count <= 1 ? kUmutexUnowned : kUmutexContested);
|
||||
auto it = chain.sleep_queue.find(key);
|
||||
it->second.thr = nullptr;
|
||||
it->second.cv.notify_one(chain.mtx);
|
||||
chain.erase(&*it);
|
||||
chain.notify_one(key);
|
||||
if (!ok)
|
||||
return ErrorCode::INVAL;
|
||||
return {};
|
||||
|
|
@ -285,11 +289,23 @@ orbis::ErrorCode orbis::umtx_wait_umutex(Thread *thread, ptr<umutex> m,
|
|||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wake_umutex(Thread *thread, ptr<void> obj,
|
||||
std::int64_t val, ptr<void> uaddr1,
|
||||
ptr<void> uaddr2) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, obj, val, uaddr1, uaddr2);
|
||||
return ErrorCode::NOSYS;
|
||||
orbis::ErrorCode orbis::umtx_wake_umutex(Thread *thread, ptr<umutex> m) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, m);
|
||||
int owner = m->owner.load(std::memory_order::acquire);
|
||||
if ((owner & ~kUmutexContested) != 0)
|
||||
return {};
|
||||
|
||||
[[maybe_unused]] uint flags = uread(&m->flags);
|
||||
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
if (count <= 1) {
|
||||
owner = kUmutexContested;
|
||||
m->owner.compare_exchange_strong(owner, kUmutexUnowned);
|
||||
}
|
||||
if (count != 0 && (owner & ~kUmutexContested) == 0)
|
||||
chain.notify_one(key);
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<void> obj,
|
||||
|
|
|
|||
Loading…
Reference in a new issue