mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-10 10:41:26 +01:00
[orbis-kernel] Stub umtx ipc support
This commit is contained in:
parent
6c7bde4faa
commit
773be7283d
|
|
@ -19,8 +19,8 @@ struct Thread;
|
|||
|
||||
struct UmtxKey {
|
||||
// TODO: may contain a reference to a shared memory
|
||||
void *addr;
|
||||
pid_t pid;
|
||||
std::uintptr_t addr;
|
||||
orbis::pid_t pid;
|
||||
|
||||
auto operator<=>(const UmtxKey &) const = default;
|
||||
};
|
||||
|
|
@ -112,21 +112,16 @@ public:
|
|||
|
||||
// Use getUmtxChain0 or getUmtxChain1
|
||||
std::tuple<UmtxChain &, UmtxKey, std::unique_lock<shared_mutex>>
|
||||
getUmtxChainIndexed(int i, pid_t pid, void *ptr) {
|
||||
auto n = reinterpret_cast<std::uintptr_t>(ptr) + pid;
|
||||
n = ((n * c_golden_ratio_prime) >> c_umtx_shifts) % c_umtx_chains;
|
||||
std::unique_lock lock(m_umtx_chains[i][n].mtx);
|
||||
return {m_umtx_chains[i][n], UmtxKey{ptr, pid}, std::move(lock)};
|
||||
}
|
||||
getUmtxChainIndexed(int i, Thread *t, uint32_t flags, void *ptr);
|
||||
|
||||
// Internal Umtx: Wait/Cv/Sem
|
||||
auto getUmtxChain0(pid_t pid, void *ptr) {
|
||||
return getUmtxChainIndexed(0, pid, ptr);
|
||||
auto getUmtxChain0(Thread *t, uint32_t flags, void *ptr) {
|
||||
return getUmtxChainIndexed(0, t, flags, ptr);
|
||||
}
|
||||
|
||||
// Internal Umtx: Mutex/Umtx/Rwlock
|
||||
auto getUmtxChain1(pid_t pid, void *ptr) {
|
||||
return getUmtxChainIndexed(1, pid, ptr);
|
||||
auto getUmtxChain1(Thread *t, uint32_t flags, void *ptr) {
|
||||
return getUmtxChainIndexed(1, t, flags, ptr);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ ErrorCode umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
|
|||
std::uint64_t ut);
|
||||
ErrorCode umtx_unlock_umtx(Thread *thread, ptr<umtx> umtx, ulong id);
|
||||
ErrorCode umtx_wait(Thread *thread, ptr<void> addr, ulong id, std::uint64_t ut,
|
||||
bool is32);
|
||||
bool is32, bool ipc);
|
||||
ErrorCode umtx_wake(Thread *thread, ptr<void> addr, sint n_wake);
|
||||
ErrorCode umtx_trylock_umutex(Thread *thread, ptr<umutex> m);
|
||||
ErrorCode umtx_lock_umutex(Thread *thread, ptr<umutex> m, std::uint64_t ut);
|
||||
|
|
|
|||
|
|
@ -178,6 +178,23 @@ void KernelContext::kfree(void *ptr, std::size_t size) {
|
|||
pthread_mutex_unlock(&m_heap_mtx);
|
||||
}
|
||||
|
||||
std::tuple<UmtxChain &, UmtxKey, std::unique_lock<shared_mutex>>
|
||||
KernelContext::getUmtxChainIndexed(int i, Thread *t, uint32_t flags,
|
||||
void *ptr) {
|
||||
auto pid = t->tproc->pid;
|
||||
if (flags & 1) {
|
||||
pid = 0; // Process shared (TODO)
|
||||
ORBIS_LOG_WARNING("Using process-shared umtx", t->tid, ptr);
|
||||
}
|
||||
auto p = reinterpret_cast<std::uintptr_t>(ptr);
|
||||
auto n = p + pid;
|
||||
if (flags & 1)
|
||||
n %= 0x4000;
|
||||
n = ((n * c_golden_ratio_prime) >> c_umtx_shifts) % c_umtx_chains;
|
||||
std::unique_lock lock(m_umtx_chains[i][n].mtx);
|
||||
return {m_umtx_chains[i][n], UmtxKey{p, pid}, std::move(lock)};
|
||||
}
|
||||
|
||||
inline namespace utils {
|
||||
void kfree(void *ptr, std::size_t size) { return g_context.kfree(ptr, size); }
|
||||
void *kalloc(std::size_t size, std::size_t align) {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
case 2: {
|
||||
return with_timeout(
|
||||
[&](std::uint64_t ut) {
|
||||
return umtx_wait(thread, obj, val, ut, false);
|
||||
return umtx_wait(thread, obj, val, ut, false, true);
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
|
@ -120,7 +120,9 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
return umtx_cv_broadcast(thread, (ptr<ucond>)obj);
|
||||
case 11: {
|
||||
return with_timeout(
|
||||
[&](std::uint64_t ut) { return umtx_wait(thread, obj, val, ut, true); },
|
||||
[&](std::uint64_t ut) {
|
||||
return umtx_wait(thread, obj, val, ut, true, true);
|
||||
},
|
||||
false);
|
||||
}
|
||||
case 12:
|
||||
|
|
@ -131,7 +133,9 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
return umtx_rw_unlock(thread, obj, val, uaddr1, uaddr2);
|
||||
case 15: {
|
||||
return with_timeout(
|
||||
[&](std::uint64_t ut) { return umtx_wait(thread, obj, val, ut, true); },
|
||||
[&](std::uint64_t ut) {
|
||||
return umtx_wait(thread, obj, val, ut, true, false);
|
||||
},
|
||||
false);
|
||||
}
|
||||
case 16:
|
||||
|
|
|
|||
|
|
@ -59,9 +59,9 @@ orbis::ErrorCode orbis::umtx_unlock_umtx(Thread *thread, ptr<umtx> umtx,
|
|||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
|
||||
std::uint64_t ut, bool is32) {
|
||||
std::uint64_t ut, bool is32, bool ipc) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, addr, id, ut, is32);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, addr);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, ipc, addr);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
ErrorCode result = {};
|
||||
ulong val = 0;
|
||||
|
|
@ -100,7 +100,7 @@ orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
|
|||
|
||||
orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr<void> addr, sint n_wake) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, addr, n_wake);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, addr);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, true, addr);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
// TODO: check this
|
||||
while (count--) {
|
||||
|
|
@ -164,7 +164,7 @@ static ErrorCode do_lock_normal(Thread *thread, ptr<umutex> m, uint flags,
|
|||
if (error != ErrorCode{})
|
||||
return error;
|
||||
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread, flags, m);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
if (m->owner.compare_exchange_strong(owner, owner | kUmutexContested)) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
|
|
@ -200,7 +200,7 @@ static ErrorCode do_unlock_normal(Thread *thread, ptr<umutex> m, uint flags) {
|
|||
return {};
|
||||
}
|
||||
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread, flags, m);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
bool ok = m->owner.compare_exchange_strong(
|
||||
owner, count <= 1 ? kUmutexUnowned : kUmutexContested);
|
||||
|
|
@ -296,7 +296,7 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, cv);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, cv->flags, cv);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
|
||||
if (!cv->has_waiters.load(std::memory_order::relaxed))
|
||||
|
|
@ -340,7 +340,7 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
|
|||
|
||||
orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr<ucond> cv) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, cv);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, cv);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, cv->flags, cv);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
if (chain.notify_one(key) >= count)
|
||||
cv->has_waiters.store(0, std::memory_order::relaxed);
|
||||
|
|
@ -349,7 +349,7 @@ orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr<ucond> cv) {
|
|||
|
||||
orbis::ErrorCode orbis::umtx_cv_broadcast(Thread *thread, ptr<ucond> cv) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, cv);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, cv);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, cv->flags, cv);
|
||||
chain.notify_all(key);
|
||||
cv->has_waiters.store(0, std::memory_order::relaxed);
|
||||
return {};
|
||||
|
|
@ -376,9 +376,18 @@ orbis::ErrorCode orbis::umtx_rw_unlock(Thread *thread, ptr<void> obj,
|
|||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr<void> uaddr,
|
||||
orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr<void> addr,
|
||||
sint n_wake) {
|
||||
return umtx_wake(thread, uaddr, n_wake);
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, thread->tid, addr, n_wake);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, false, addr);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
// TODO: check this
|
||||
while (count--) {
|
||||
chain.notify_one(key);
|
||||
if (n_wake-- <= 1)
|
||||
break;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wait_umutex(Thread *thread, ptr<umutex> m,
|
||||
|
|
@ -404,11 +413,11 @@ orbis::ErrorCode orbis::umtx_wake_umutex(Thread *thread, ptr<umutex> m) {
|
|||
if ((owner & ~kUmutexContested) != 0)
|
||||
return {};
|
||||
|
||||
[[maybe_unused]] uint flags;
|
||||
uint flags;
|
||||
if (ErrorCode err = uread(flags, &m->flags); err != ErrorCode{})
|
||||
return err;
|
||||
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread, flags, m);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
if (count <= 1) {
|
||||
owner = kUmutexContested;
|
||||
|
|
@ -422,7 +431,7 @@ orbis::ErrorCode orbis::umtx_wake_umutex(Thread *thread, ptr<umutex> m) {
|
|||
orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem,
|
||||
std::uint64_t ut) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, sem, ut);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, sem);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, sem->flags, sem);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
|
||||
std::uint32_t has_waiters = sem->has_waiters;
|
||||
|
|
@ -465,7 +474,7 @@ orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<usem> sem,
|
|||
|
||||
orbis::ErrorCode orbis::umtx_sem_wake(Thread *thread, ptr<usem> sem) {
|
||||
ORBIS_LOG_WARNING(__FUNCTION__, sem);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, sem);
|
||||
auto [chain, key, lock] = g_context.getUmtxChain0(thread, sem->flags, sem);
|
||||
std::size_t count = chain.sleep_queue.count(key);
|
||||
if (chain.notify_one(key) >= count)
|
||||
sem->has_waiters.store(0, std::memory_order::relaxed);
|
||||
|
|
|
|||
Loading…
Reference in a new issue