[orbis-kernel] Implement _umtx_op for umutex (no PI)

This commit is contained in:
Ivan Chikish 2023-07-10 13:58:53 +03:00
parent d273e649bd
commit bfffd20946
4 changed files with 328 additions and 94 deletions

View file

@ -1,16 +1,44 @@
#pragma once
#include "evf.hpp"
#include "utils/LinkedNode.hpp"
#include "utils/SharedCV.hpp"
#include "utils/SharedMutex.hpp"
#include "KernelAllocator.hpp"
#include "orbis/thread/types.hpp"
#include <algorithm>
#include <cstdint>
#include <mutex>
#include <pthread.h>
#include <utility>
namespace orbis {
struct Process;
struct Thread;
struct UmtxKey {
// TODO: may contain a reference to a shared memory
void *addr;
pid_t pid;
auto operator<=>(const UmtxKey &) const = default;
};
struct UmtxCond {
Thread *thr;
utils::shared_cv cv;
UmtxCond(Thread *thr) : thr(thr) {}
};
struct UmtxChain {
utils::shared_mutex mtx;
utils::kmultimap<UmtxKey, UmtxCond> sleep_queue;
utils::kmultimap<UmtxKey, UmtxCond> spare_queue;
std::pair<const UmtxKey, UmtxCond> *enqueue(UmtxKey &key, Thread *thr);
void erase(std::pair<const UmtxKey, UmtxCond> *obj);
};
class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {
public:
@ -47,6 +75,31 @@ public:
return {};
}
enum {
c_golden_ratio_prime = 2654404609u,
c_umtx_chains = 512,
c_umtx_shifts = 23,
};
// 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)};
}
// Internal Umtx: Wait/Cv/Sem
auto getUmtxChain0(pid_t pid, void *ptr) {
return getUmtxChainIndexed(0, pid, ptr);
}
// Internal Umtx: Mutex/Umtx/Rwlock
auto getUmtxChain1(pid_t pid, void *ptr) {
return getUmtxChainIndexed(1, pid, ptr);
}
private:
shared_mutex m_evf_mtx;
mutable pthread_mutex_t m_heap_mtx;
@ -55,6 +108,8 @@ private:
utils::kmultimap<std::size_t, void *> m_free_heap;
utils::kmultimap<std::size_t, void *> m_used_node;
UmtxChain m_umtx_chains[2][c_umtx_chains]{};
mutable shared_mutex m_proc_mtx;
utils::LinkedNode<Process> *m_processes = nullptr;
utils::kmap<utils::kstring, Ref<EventFlag>> m_event_flags;

View file

@ -61,22 +61,21 @@ struct usem {
struct Thread;
ErrorCode umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
timespec *ts);
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,
timespec *timeout);
ErrorCode umtx_wait(Thread *thread, ptr<void> addr, ulong id, std::uint64_t ut);
ErrorCode umtx_wake(Thread *thread, ptr<void> uaddr, sint n_wake);
ErrorCode umtx_trylock_umutex(Thread *thread, ptr<umutex> m);
ErrorCode umtx_lock_umutex(Thread *thread, ptr<umutex> m, timespec *timeout);
ErrorCode umtx_lock_umutex(Thread *thread, ptr<umutex> m, std::uint64_t ut);
ErrorCode umtx_unlock_umutex(Thread *thread, ptr<umutex> m);
ErrorCode umtx_set_ceiling(Thread *thread, ptr<umutex> m, std::uint32_t ceiling,
ptr<uint32_t> oldCeiling);
ErrorCode umtx_cv_wait(Thread *thread, ptr<ucond> cv, ptr<umutex> m,
timespec *ts, ulong wflags);
std::uint64_t ut, ulong wflags);
ErrorCode umtx_cv_signal(Thread *thread, ptr<ucond> cv);
ErrorCode umtx_cv_broadcast(Thread *thread, ptr<ucond> cv);
ErrorCode umtx_wait_uint(Thread *thread, ptr<void> addr, ulong id,
timespec *timeout);
std::uint64_t ut);
ErrorCode umtx_rw_rdlock(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_rw_wrlock(Thread *thread, ptr<void> obj, std::int64_t val,
@ -84,9 +83,9 @@ ErrorCode umtx_rw_wrlock(Thread *thread, ptr<void> obj, std::int64_t val,
ErrorCode umtx_rw_unlock(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_wait_uint_private(Thread *thread, ptr<void> addr, ulong id,
timespec *timeout);
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, timespec *timeout);
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_sem_wait(Thread *thread, ptr<void> obj, std::int64_t val,