mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-24 01:20:44 +01:00
[orbis-kernel] Implement _umtx_op for umutex (no PI)
This commit is contained in:
parent
d273e649bd
commit
bfffd20946
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#include "orbis/utils/Logs.hpp"
|
||||
#include "sys/sysproto.hpp"
|
||||
#include "time.hpp"
|
||||
#include "umtx.hpp"
|
||||
#include <chrono>
|
||||
|
||||
static orbis::ErrorCode ureadTimespec(orbis::timespec &ts,
|
||||
orbis::ptr<orbis::timespec> addr) {
|
||||
|
|
@ -13,16 +15,24 @@ static orbis::ErrorCode ureadTimespec(orbis::timespec &ts,
|
|||
}
|
||||
|
||||
orbis::SysResult orbis::sys__umtx_lock(Thread *thread, ptr<umtx> umtx) {
|
||||
return umtx_lock_umtx(thread, umtx, thread->tid, nullptr);
|
||||
ORBIS_LOG_TODO(__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);
|
||||
if (reinterpret_cast<std::uintptr_t>(umtx) - 0x10000 > 0xff'fffe'ffff)
|
||||
return ErrorCode::FAULT;
|
||||
return umtx_unlock_umtx(thread, umtx, thread->tid);
|
||||
}
|
||||
orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
||||
ulong val, ptr<void> uaddr1,
|
||||
ptr<void> uaddr2) {
|
||||
switch (op) {
|
||||
case 0: {
|
||||
ORBIS_LOG_TODO(__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 {
|
||||
timespec *ts = nullptr;
|
||||
timespec timeout;
|
||||
if (uaddr2 != nullptr) {
|
||||
|
|
@ -33,41 +43,49 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
|
||||
ts = &timeout;
|
||||
}
|
||||
std::uint64_t usec = 0;
|
||||
auto start = std::chrono::steady_clock::now();
|
||||
|
||||
return umtx_lock_umtx(thread, (ptr<umtx>)obj, val, ts);
|
||||
if (!ts) {
|
||||
usec = -1;
|
||||
while (true) {
|
||||
if (auto r = op(usec); r != ErrorCode::TIMEDOUT)
|
||||
return r;
|
||||
}
|
||||
} else {
|
||||
usec += (timeout.nsec + 999) / 1000;
|
||||
usec += timeout.sec * 1000'000;
|
||||
std::uint64_t udiff = 0;
|
||||
while (true) {
|
||||
if (auto r = op(usec - udiff); r != ErrorCode::TIMEDOUT)
|
||||
return r;
|
||||
udiff = (std::chrono::steady_clock::now() - start).count() / 1000;
|
||||
if (udiff >= usec)
|
||||
return ErrorCode::TIMEDOUT;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
switch (op) {
|
||||
case 0: {
|
||||
return with_timeout([&](std::uint64_t ut) {
|
||||
return umtx_lock_umtx(thread, (ptr<umtx>)obj, val, ut);
|
||||
});
|
||||
}
|
||||
case 1:
|
||||
return umtx_unlock_umtx(thread, (ptr<umtx>)obj, val);
|
||||
case 2: {
|
||||
timespec *ts = nullptr;
|
||||
timespec timeout;
|
||||
if (uaddr2 != nullptr) {
|
||||
auto result = ureadTimespec(timeout, (ptr<timespec>)uaddr2);
|
||||
if (result != ErrorCode{}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ts = &timeout;
|
||||
}
|
||||
|
||||
return umtx_wait(thread, obj, val, ts);
|
||||
return with_timeout(
|
||||
[&](std::uint64_t ut) { return umtx_wait(thread, obj, val, ut); });
|
||||
}
|
||||
case 3:
|
||||
return umtx_wake(thread, obj, val);
|
||||
case 4:
|
||||
return umtx_trylock_umutex(thread, (ptr<umutex>)obj);
|
||||
case 5: {
|
||||
timespec *ts = nullptr;
|
||||
timespec timeout;
|
||||
if (uaddr2 != nullptr) {
|
||||
auto result = ureadTimespec(timeout, (ptr<timespec>)uaddr2);
|
||||
if (result != ErrorCode{}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ts = &timeout;
|
||||
}
|
||||
return umtx_lock_umutex(thread, (ptr<umutex>)obj, ts);
|
||||
return with_timeout([&](std::uint64_t ut) {
|
||||
return umtx_lock_umutex(thread, (ptr<umutex>)obj, ut);
|
||||
});
|
||||
}
|
||||
case 6:
|
||||
return umtx_unlock_umutex(thread, (ptr<umutex>)obj);
|
||||
|
|
@ -76,18 +94,10 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
(ptr<uint32_t>)uaddr1);
|
||||
|
||||
case 8: {
|
||||
timespec *ts = nullptr;
|
||||
timespec timeout;
|
||||
if (uaddr2 != nullptr) {
|
||||
auto result = ureadTimespec(timeout, (ptr<timespec>)uaddr2);
|
||||
if (result != ErrorCode{}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ts = &timeout;
|
||||
}
|
||||
|
||||
return umtx_cv_wait(thread, (ptr<ucond>)obj, (ptr<umutex>)uaddr1, ts, val);
|
||||
return with_timeout([&](std::uint64_t ut) {
|
||||
return umtx_cv_wait(thread, (ptr<ucond>)obj, (ptr<umutex>)uaddr1, ut,
|
||||
val);
|
||||
});
|
||||
}
|
||||
|
||||
case 9:
|
||||
|
|
@ -95,18 +105,8 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
case 10:
|
||||
return umtx_cv_broadcast(thread, (ptr<ucond>)obj);
|
||||
case 11: {
|
||||
timespec *ts = nullptr;
|
||||
timespec timeout;
|
||||
if (uaddr2 != nullptr) {
|
||||
auto result = ureadTimespec(timeout, (ptr<timespec>)uaddr2);
|
||||
if (result != ErrorCode{}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ts = &timeout;
|
||||
}
|
||||
|
||||
return umtx_wait_uint(thread, obj, val, ts);
|
||||
return with_timeout(
|
||||
[&](std::uint64_t ut) { return umtx_wait_uint(thread, obj, val, ut); });
|
||||
}
|
||||
case 12:
|
||||
return umtx_rw_rdlock(thread, obj, val, uaddr1, uaddr2);
|
||||
|
|
@ -115,34 +115,16 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|||
case 14:
|
||||
return umtx_rw_unlock(thread, obj, val, uaddr1, uaddr2);
|
||||
case 15: {
|
||||
timespec *ts = nullptr;
|
||||
timespec timeout;
|
||||
if (uaddr2 != nullptr) {
|
||||
auto result = ureadTimespec(timeout, (ptr<timespec>)uaddr2);
|
||||
if (result != ErrorCode{}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ts = &timeout;
|
||||
}
|
||||
|
||||
return umtx_wait_uint_private(thread, obj, val, ts);
|
||||
return with_timeout([&](std::uint64_t ut) {
|
||||
return umtx_wait_uint_private(thread, obj, val, ut);
|
||||
});
|
||||
}
|
||||
case 16:
|
||||
return umtx_wake_private(thread, obj, val);
|
||||
case 17: {
|
||||
timespec *ts = nullptr;
|
||||
timespec timeout;
|
||||
if (uaddr2 != nullptr) {
|
||||
auto result = ureadTimespec(timeout, (ptr<timespec>)uaddr2);
|
||||
if (result != ErrorCode{}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ts = &timeout;
|
||||
}
|
||||
|
||||
return umtx_wait_umutex(thread, (ptr<umutex>)obj, ts);
|
||||
return with_timeout([&](std::uint64_t ut) {
|
||||
return umtx_wait_umutex(thread, (ptr<umutex>)obj, ut);
|
||||
});
|
||||
}
|
||||
case 18:
|
||||
return umtx_wake_umutex(thread, obj, val, uaddr1, uaddr2);
|
||||
|
|
|
|||
|
|
@ -1,122 +1,320 @@
|
|||
#include "umtx.hpp"
|
||||
#include "orbis/KernelContext.hpp"
|
||||
#include "orbis/thread.hpp"
|
||||
#include "orbis/utils/AtomicOp.hpp"
|
||||
#include "orbis/utils/Logs.hpp"
|
||||
#include "time.hpp"
|
||||
|
||||
namespace orbis {
|
||||
std::pair<const UmtxKey, UmtxCond> *UmtxChain::enqueue(UmtxKey &key,
|
||||
Thread *thr) {
|
||||
if (!spare_queue.empty()) {
|
||||
auto node = spare_queue.extract(spare_queue.begin());
|
||||
node.key() = key;
|
||||
node.mapped().thr = thr;
|
||||
return &*sleep_queue.insert(std::move(node));
|
||||
}
|
||||
return &*sleep_queue.emplace(key, thr);
|
||||
}
|
||||
|
||||
void UmtxChain::erase(std::pair<const UmtxKey, UmtxCond> *obj) {
|
||||
for (auto [it, e] = sleep_queue.equal_range(obj->first); it != e; it++) {
|
||||
if (&*it == obj) {
|
||||
auto node = sleep_queue.extract(it);
|
||||
node.key() = {};
|
||||
spare_queue.insert(spare_queue.begin(), std::move(node));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace orbis
|
||||
|
||||
orbis::ErrorCode orbis::umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
|
||||
timespec *ts) {
|
||||
std::uint64_t ut) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, umtx, id, ut);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_unlock_umtx(Thread *thread, ptr<umtx> umtx,
|
||||
ulong id) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, umtx, id);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
|
||||
timespec *timeout) {
|
||||
std::uint64_t ut) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, addr, id, ut);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr<void> uaddr,
|
||||
sint n_wake) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, uaddr, n_wake);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_trylock_umutex(Thread *thread, ptr<umutex> m) {
|
||||
namespace orbis {
|
||||
enum class umutex_lock_mode {
|
||||
lock,
|
||||
try_,
|
||||
wait,
|
||||
};
|
||||
template <>
|
||||
void log_class_string<umutex_lock_mode>::format(std::string &out,
|
||||
const void *arg) {
|
||||
switch (get_object(arg)) {
|
||||
case umutex_lock_mode::lock:
|
||||
out += "lock";
|
||||
break;
|
||||
case umutex_lock_mode::try_:
|
||||
out += "try";
|
||||
break;
|
||||
case umutex_lock_mode::wait:
|
||||
out += "wait";
|
||||
break;
|
||||
}
|
||||
}
|
||||
static ErrorCode do_lock_normal(Thread *thread, ptr<umutex> m, uint flags,
|
||||
std::uint64_t ut, umutex_lock_mode mode) {
|
||||
ORBIS_LOG_NOTICE(__FUNCTION__, m, flags, ut, mode);
|
||||
ErrorCode error = {};
|
||||
while (true) {
|
||||
int owner = m->owner.load(std::memory_order_acquire);
|
||||
if (mode == umutex_lock_mode::wait) {
|
||||
if (owner == kUmutexUnowned || owner == kUmutexContested)
|
||||
return {};
|
||||
} else {
|
||||
owner = kUmutexUnowned;
|
||||
if (m->owner.compare_exchange_strong(owner, thread->tid))
|
||||
return {};
|
||||
if (owner == kUmutexContested) {
|
||||
if (m->owner.compare_exchange_strong(owner,
|
||||
thread->tid | kUmutexContested))
|
||||
return {};
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & kUmutexErrorCheck) != 0 &&
|
||||
(owner & ~kUmutexContested) == thread->tid)
|
||||
return ErrorCode::DEADLK;
|
||||
|
||||
if (mode == umutex_lock_mode::try_)
|
||||
return ErrorCode::BUSY;
|
||||
|
||||
if (error != ErrorCode{})
|
||||
return error;
|
||||
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m);
|
||||
auto node = chain.enqueue(key, thread);
|
||||
bool ok = m->owner.compare_exchange_strong(owner, owner | kUmutexContested);
|
||||
if (ok && node->second.thr == thread) {
|
||||
node->second.cv.wait(chain.mtx, ut);
|
||||
if (node->second.thr)
|
||||
error = ErrorCode::TIMEDOUT;
|
||||
}
|
||||
if (node->second.thr == thread)
|
||||
chain.erase(node);
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
static ErrorCode do_lock_pi(Thread *thread, ptr<umutex> m, uint flags,
|
||||
std::uint64_t ut, umutex_lock_mode mode) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, m, flags, ut, mode);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
static ErrorCode do_lock_pp(Thread *thread, ptr<umutex> m, uint flags,
|
||||
std::uint64_t ut, umutex_lock_mode mode) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, m, flags, ut, mode);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
static ErrorCode do_unlock_normal(Thread *thread, ptr<umutex> m, uint flags) {
|
||||
ORBIS_LOG_NOTICE(__FUNCTION__, m, flags);
|
||||
|
||||
int owner = m->owner.load(std::memory_order_acquire);
|
||||
if ((owner & ~kUmutexContested) != thread->tid)
|
||||
return ErrorCode::PERM;
|
||||
|
||||
if ((owner & kUmtxContested) == 0) {
|
||||
if (m->owner.compare_exchange_strong(owner, kUmutexUnowned))
|
||||
return {};
|
||||
}
|
||||
|
||||
auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m);
|
||||
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);
|
||||
if (!ok)
|
||||
return ErrorCode::INVAL;
|
||||
return {};
|
||||
}
|
||||
static ErrorCode do_unlock_pi(Thread *thread, ptr<umutex> m, uint flags) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, m, flags);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
static ErrorCode do_unlock_pp(Thread *thread, ptr<umutex> m, uint flags) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, m, flags);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
} // namespace orbis
|
||||
|
||||
orbis::ErrorCode orbis::umtx_trylock_umutex(Thread *thread, ptr<umutex> m) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, m);
|
||||
uint flags = uread(&m->flags);
|
||||
switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) {
|
||||
case 0:
|
||||
return do_lock_normal(thread, m, flags, 0, umutex_lock_mode::try_);
|
||||
case kUmutexPrioInherit:
|
||||
return do_lock_pi(thread, m, flags, 0, umutex_lock_mode::try_);
|
||||
case kUmutexPrioProtect:
|
||||
return do_lock_pp(thread, m, flags, 0, umutex_lock_mode::try_);
|
||||
}
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_lock_umutex(Thread *thread, ptr<umutex> m,
|
||||
timespec *timeout) {
|
||||
return ErrorCode::NOSYS;
|
||||
std::uint64_t ut) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, m, ut);
|
||||
uint flags = uread(&m->flags);
|
||||
switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) {
|
||||
case 0:
|
||||
return do_lock_normal(thread, m, flags, ut, umutex_lock_mode::lock);
|
||||
case kUmutexPrioInherit:
|
||||
return do_lock_pi(thread, m, flags, ut, umutex_lock_mode::lock);
|
||||
case kUmutexPrioProtect:
|
||||
return do_lock_pp(thread, m, flags, ut, umutex_lock_mode::lock);
|
||||
}
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_unlock_umutex(Thread *thread, ptr<umutex> m) {
|
||||
return ErrorCode::NOSYS;
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, m);
|
||||
uint flags = uread(&m->flags);
|
||||
switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) {
|
||||
case 0:
|
||||
return do_unlock_normal(thread, m, flags);
|
||||
case kUmutexPrioInherit:
|
||||
return do_unlock_pi(thread, m, flags);
|
||||
case kUmutexPrioProtect:
|
||||
return do_unlock_pp(thread, m, flags);
|
||||
}
|
||||
return ErrorCode::INVAL;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_set_ceiling(Thread *thread, ptr<umutex> m,
|
||||
std::uint32_t ceiling,
|
||||
ptr<uint32_t> oldCeiling) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, m, ceiling, oldCeiling);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
|
||||
ptr<umutex> m, timespec *ts,
|
||||
ptr<umutex> m, std::uint64_t ut,
|
||||
ulong wflags) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, cv, m, ut, wflags);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr<ucond> cv) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, cv);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_cv_broadcast(Thread *thread, ptr<ucond> cv) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, cv);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wait_uint(Thread *thread, ptr<void> addr, ulong id,
|
||||
timespec *timeout) {
|
||||
std::uint64_t ut) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, addr, id, ut);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_rw_rdlock(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_rw_wrlock(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_rw_unlock(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_wait_uint_private(Thread *thread, ptr<void> addr,
|
||||
ulong id, timespec *timeout) {
|
||||
ulong id, std::uint64_t ut) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, addr, id, ut);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr<void> uaddr,
|
||||
sint n_wake) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, uaddr, n_wake);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wait_umutex(Thread *thread, ptr<umutex> m,
|
||||
timespec *timeout) {
|
||||
return ErrorCode::NOSYS;
|
||||
std::uint64_t ut) {
|
||||
ORBIS_LOG_TRACE(__FUNCTION__, m, ut);
|
||||
uint flags = uread(&m->flags);
|
||||
switch (flags & (kUmutexPrioInherit | kUmutexPrioProtect)) {
|
||||
case 0:
|
||||
return do_lock_normal(thread, m, flags, ut, umutex_lock_mode::wait);
|
||||
case kUmutexPrioInherit:
|
||||
return do_lock_pi(thread, m, flags, ut, umutex_lock_mode::wait);
|
||||
case kUmutexPrioProtect:
|
||||
return do_lock_pp(thread, m, flags, ut, umutex_lock_mode::wait);
|
||||
}
|
||||
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_sem_wait(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_sem_wake(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_nwake_private(Thread *thread, ptr<void> uaddrs,
|
||||
std::int64_t count) {
|
||||
ORBIS_LOG_TODO(__FUNCTION__, uaddrs, count);
|
||||
return ErrorCode::NOSYS;
|
||||
}
|
||||
|
||||
orbis::ErrorCode orbis::umtx_wake2_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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue