[orbis-kernel] umtx: read timeout

This commit is contained in:
DH 2023-07-09 13:52:38 +03:00
parent cae3d4ec7a
commit 23fcf2747a
4 changed files with 233 additions and 114 deletions

View file

@ -2,54 +2,99 @@
#include "error/ErrorCode.hpp"
#include "orbis-config.hpp"
#include "thread/types.hpp"
#include "time.hpp"
#include <atomic>
#include <limits>
namespace orbis {
inline constexpr ulong kUmtxUnowned = 0;
inline constexpr ulong kUmtxContested = std::numeric_limits<slong>::min();
inline constexpr auto kUsyncProcessShared = 1;
inline constexpr auto kUmutexUnowned = 0;
inline constexpr auto kUmutexContested = 0x80000000;
inline constexpr auto kUmutexErrorCheck = 2;
inline constexpr auto kUmutexPrioInherit = 4;
inline constexpr auto kUmutexPrioProtect = 8;
inline constexpr auto kUrwLockPreferReader = 2;
inline constexpr auto kUrwLockWriteOwner = 0x80000000;
inline constexpr auto kUrwLockWriteWaiters = 0x40000000;
inline constexpr auto kUrwLockReadWaiters = 0x20000000;
inline constexpr auto kUrwLockMaxReaders = 0x1fffffff;
inline constexpr auto kSemNamed = 2;
struct umtx {
std::atomic<ulong> owner; // Owner of the mutex
};
struct umutex {
std::atomic<lwpid_t> owner; // Owner of the mutex
uint32_t flags; // Flags of the mutex
uint32_t ceilings[2]; // Priority protect ceiling
uint32_t spare[4];
};
struct ucond {
std::atomic<uint32_t> has_waiters; // Has waiters in kernel
uint32_t flags; // Flags of the condition variable
uint32_t clockid; // Clock id
uint32_t spare[1]; // Spare space
};
struct urwlock {
std::atomic<int32_t> state;
uint32_t flags;
uint32_t blocked_readers;
uint32_t blocked_writers;
uint32_t spare[4];
};
struct usem {
std::atomic<uint32_t> has_waiters;
std::atomic<uint32_t> count;
uint32_t flags;
};
struct Thread;
ErrorCode umtx_lock_umtx(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_unlock_umtx(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_wait(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_wake(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_trylock_umutex(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_lock_umutex(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_unlock_umutex(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_set_ceiling(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_cv_wait(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_cv_signal(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_cv_broadcast(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_wait_uint(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
timespec *ts);
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_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_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);
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);
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,
ptr<void> uaddr1, ptr<void> uaddr2);
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> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2);
ErrorCode umtx_wake_private(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_wait_umutex(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);
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_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,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_sem_wake(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_nwake_private(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
ErrorCode umtx_nwake_private(Thread *thread, ptr<void> uaddrs,
std::int64_t count);
ErrorCode umtx_wake2_umutex(Thread *thread, ptr<void> obj, std::int64_t val,
ptr<void> uaddr1, ptr<void> uaddr2);
} // namespace orbis

View file

@ -53,10 +53,6 @@ orbis::SysResult orbis::sys_regmgr_call(Thread *thread, uint32_t op,
};
auto int_value = reinterpret_cast<nonsys_int *>(value);
const char *const string = "someString";
ORBIS_LOG_TODO(__FUNCTION__, string);
ORBIS_LOG_TODO(
__FUNCTION__, int_value->encoded_id,
int_value->encoded_id_parts.data[0],

View file

@ -1,53 +1,149 @@
#include "sys/sysproto.hpp"
#include "time.hpp"
#include "umtx.hpp"
orbis::SysResult orbis::sys__umtx_lock(Thread *thread, ptr<struct umtx> umtx) {
return umtx_lock_umtx(thread, umtx, 0, 0, 0);
static orbis::ErrorCode ureadTimespec(orbis::timespec &ts,
orbis::ptr<orbis::timespec> addr) {
ts = uread(addr);
if (ts.sec < 0 || ts.nsec < 0 || ts.nsec > 1000000000) {
return orbis::ErrorCode::INVAL;
}
return {};
}
orbis::SysResult orbis::sys__umtx_unlock(Thread *thread,
ptr<struct umtx> umtx) {
return umtx_lock_umtx(thread, umtx, thread->tid, 0, 0);
orbis::SysResult orbis::sys__umtx_lock(Thread *thread, ptr<umtx> umtx) {
return umtx_lock_umtx(thread, umtx, thread->tid, nullptr);
}
orbis::SysResult orbis::sys__umtx_unlock(Thread *thread, ptr<umtx> umtx) {
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:
return umtx_lock_umtx(thread, obj, val, uaddr1, uaddr2);
case 0: {
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_umtx(thread, (ptr<umtx>)obj, val, ts);
}
case 1:
return umtx_unlock_umtx(thread, obj, val, uaddr1, uaddr2);
case 2:
return umtx_wait(thread, obj, val, uaddr1, uaddr2);
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);
}
case 3:
return umtx_wake(thread, obj, val, uaddr1, uaddr2);
return umtx_wake(thread, obj, val);
case 4:
return umtx_trylock_umutex(thread, obj, val, uaddr1, uaddr2);
case 5:
return umtx_lock_umutex(thread, obj, val, uaddr1, uaddr2);
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);
}
case 6:
return umtx_unlock_umutex(thread, obj, val, uaddr1, uaddr2);
return umtx_unlock_umutex(thread, (ptr<umutex>)obj);
case 7:
return umtx_set_ceiling(thread, obj, val, uaddr1, uaddr2);
case 8:
return umtx_cv_wait(thread, obj, val, uaddr1, uaddr2);
return umtx_set_ceiling(thread, (ptr<umutex>)obj, val,
(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);
}
case 9:
return umtx_cv_signal(thread, obj, val, uaddr1, uaddr2);
return umtx_cv_signal(thread, (ptr<ucond>)obj);
case 10:
return umtx_cv_broadcast(thread, obj, val, uaddr1, uaddr2);
case 11:
return umtx_wait_uint(thread, obj, val, uaddr1, uaddr2);
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);
}
case 12:
return umtx_rw_rdlock(thread, obj, val, uaddr1, uaddr2);
case 13:
return umtx_rw_wrlock(thread, obj, val, uaddr1, uaddr2);
case 14:
return umtx_rw_unlock(thread, obj, val, uaddr1, uaddr2);
case 15:
return umtx_wait_uint_private(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);
}
case 16:
return umtx_wake_private(thread, obj, val, uaddr1, uaddr2);
case 17:
return umtx_wait_umutex(thread, obj, val, uaddr1, uaddr2);
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);
}
case 18:
return umtx_wake_umutex(thread, obj, val, uaddr1, uaddr2);
case 19:
@ -55,7 +151,7 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
case 20:
return umtx_sem_wake(thread, obj, val, uaddr1, uaddr2);
case 21:
return umtx_nwake_private(thread, obj, val, uaddr1, uaddr2);
return umtx_nwake_private(thread, obj, val);
case 22:
return umtx_wake2_umutex(thread, obj, val, uaddr1, uaddr2);
}

View file

@ -1,74 +1,61 @@
#include "umtx.hpp"
#include "time.hpp"
orbis::ErrorCode orbis::umtx_lock_umtx(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
timespec *ts) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_unlock_umtx(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_unlock_umtx(Thread *thread, ptr<umtx> umtx,
ulong id) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_wait(Thread *thread, ptr<void> addr, ulong id,
timespec *timeout) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_wake(Thread *thread, ptr<void> uaddr,
sint n_wake) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_trylock_umutex(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_trylock_umutex(Thread *thread, ptr<umutex> m) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_lock_umutex(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_lock_umutex(Thread *thread, ptr<umutex> m,
timespec *timeout) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_unlock_umutex(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_unlock_umutex(Thread *thread, ptr<umutex> m) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_set_ceiling(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_set_ceiling(Thread *thread, ptr<umutex> m,
std::uint32_t ceiling,
ptr<uint32_t> oldCeiling) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
ptr<umutex> m, timespec *ts,
ulong wflags) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr<ucond> cv) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_cv_broadcast(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_cv_broadcast(Thread *thread, ptr<ucond> cv) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_wait_uint(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_wait_uint(Thread *thread, ptr<void> addr, ulong id,
timespec *timeout) {
return ErrorCode::NOSYS;
}
@ -90,22 +77,18 @@ orbis::ErrorCode orbis::umtx_rw_unlock(Thread *thread, ptr<void> obj,
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_wait_uint_private(Thread *thread, ptr<void> obj,
std::int64_t val,
ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_wait_uint_private(Thread *thread, ptr<void> addr,
ulong id, timespec *timeout) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_wake_private(Thread *thread, ptr<void> uaddr,
sint n_wake) {
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_wait_umutex(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_wait_umutex(Thread *thread, ptr<umutex> m,
timespec *timeout) {
return ErrorCode::NOSYS;
}
@ -127,9 +110,8 @@ orbis::ErrorCode orbis::umtx_sem_wake(Thread *thread, ptr<void> obj,
return ErrorCode::NOSYS;
}
orbis::ErrorCode orbis::umtx_nwake_private(Thread *thread, ptr<void> obj,
std::int64_t val, ptr<void> uaddr1,
ptr<void> uaddr2) {
orbis::ErrorCode orbis::umtx_nwake_private(Thread *thread, ptr<void> uaddrs,
std::int64_t count) {
return ErrorCode::NOSYS;
}