From 773be7283dab3f974ccb801ff46e71dab6615bf7 Mon Sep 17 00:00:00 2001 From: Ivan Chikish Date: Sat, 22 Jul 2023 12:03:46 +0300 Subject: [PATCH] [orbis-kernel] Stub umtx ipc support --- orbis-kernel/include/orbis/KernelContext.hpp | 19 ++++------ orbis-kernel/include/orbis/umtx.hpp | 2 +- orbis-kernel/src/KernelContext.cpp | 17 +++++++++ orbis-kernel/src/sys/sys_umtx.cpp | 10 ++++-- orbis-kernel/src/umtx.cpp | 37 ++++++++++++-------- 5 files changed, 55 insertions(+), 30 deletions(-) diff --git a/orbis-kernel/include/orbis/KernelContext.hpp b/orbis-kernel/include/orbis/KernelContext.hpp index 250467ecf..1970bb98b 100644 --- a/orbis-kernel/include/orbis/KernelContext.hpp +++ b/orbis-kernel/include/orbis/KernelContext.hpp @@ -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> - getUmtxChainIndexed(int i, pid_t pid, void *ptr) { - auto n = reinterpret_cast(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: diff --git a/orbis-kernel/include/orbis/umtx.hpp b/orbis-kernel/include/orbis/umtx.hpp index 6ca0e1a1e..480ec62de 100644 --- a/orbis-kernel/include/orbis/umtx.hpp +++ b/orbis-kernel/include/orbis/umtx.hpp @@ -68,7 +68,7 @@ ErrorCode umtx_lock_umtx(Thread *thread, ptr umtx, ulong id, std::uint64_t ut); ErrorCode umtx_unlock_umtx(Thread *thread, ptr umtx, ulong id); ErrorCode umtx_wait(Thread *thread, ptr addr, ulong id, std::uint64_t ut, - bool is32); + bool is32, bool ipc); ErrorCode umtx_wake(Thread *thread, ptr addr, sint n_wake); ErrorCode umtx_trylock_umutex(Thread *thread, ptr m); ErrorCode umtx_lock_umutex(Thread *thread, ptr m, std::uint64_t ut); diff --git a/orbis-kernel/src/KernelContext.cpp b/orbis-kernel/src/KernelContext.cpp index 7e5a8fd2b..d90e4a29e 100644 --- a/orbis-kernel/src/KernelContext.cpp +++ b/orbis-kernel/src/KernelContext.cpp @@ -178,6 +178,23 @@ void KernelContext::kfree(void *ptr, std::size_t size) { pthread_mutex_unlock(&m_heap_mtx); } +std::tuple> +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(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) { diff --git a/orbis-kernel/src/sys/sys_umtx.cpp b/orbis-kernel/src/sys/sys_umtx.cpp index df503dc2e..0e8d6a936 100644 --- a/orbis-kernel/src/sys/sys_umtx.cpp +++ b/orbis-kernel/src/sys/sys_umtx.cpp @@ -86,7 +86,7 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr 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 obj, sint op, return umtx_cv_broadcast(thread, (ptr)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 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: diff --git a/orbis-kernel/src/umtx.cpp b/orbis-kernel/src/umtx.cpp index 7015729a8..ad0dc8b65 100644 --- a/orbis-kernel/src/umtx.cpp +++ b/orbis-kernel/src/umtx.cpp @@ -59,9 +59,9 @@ orbis::ErrorCode orbis::umtx_unlock_umtx(Thread *thread, ptr umtx, } orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr 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 addr, ulong id, orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr 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 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 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 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 cv, orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr 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 cv) { orbis::ErrorCode orbis::umtx_cv_broadcast(Thread *thread, ptr 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 obj, return ErrorCode::NOSYS; } -orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr uaddr, +orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr 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 m, @@ -404,11 +413,11 @@ orbis::ErrorCode orbis::umtx_wake_umutex(Thread *thread, ptr 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 m) { orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr 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 sem, orbis::ErrorCode orbis::umtx_sem_wake(Thread *thread, ptr 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);