2023-07-10 12:58:53 +02:00
|
|
|
#include "orbis/utils/Logs.hpp"
|
2023-07-03 13:10:16 +02:00
|
|
|
#include "sys/sysproto.hpp"
|
2023-07-09 12:52:38 +02:00
|
|
|
#include "time.hpp"
|
2023-07-08 01:50:45 +02:00
|
|
|
#include "umtx.hpp"
|
2023-07-10 12:58:53 +02:00
|
|
|
#include <chrono>
|
2023-07-03 13:10:16 +02:00
|
|
|
|
2023-07-09 12:52:38 +02:00
|
|
|
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_lock(Thread *thread, ptr<umtx> umtx) {
|
2023-07-10 12:58:53 +02:00
|
|
|
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);
|
2023-07-06 18:16:25 +02:00
|
|
|
}
|
2023-07-09 12:52:38 +02:00
|
|
|
orbis::SysResult orbis::sys__umtx_unlock(Thread *thread, ptr<umtx> umtx) {
|
2023-07-10 12:58:53 +02:00
|
|
|
ORBIS_LOG_TODO(__FUNCTION__, umtx);
|
|
|
|
|
if (reinterpret_cast<std::uintptr_t>(umtx) - 0x10000 > 0xff'fffe'ffff)
|
|
|
|
|
return ErrorCode::FAULT;
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_unlock_umtx(thread, umtx, thread->tid);
|
2023-07-06 18:16:25 +02:00
|
|
|
}
|
|
|
|
|
orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
|
|
|
|
|
ulong val, ptr<void> uaddr1,
|
|
|
|
|
ptr<void> uaddr2) {
|
2023-07-10 12:58:53 +02:00
|
|
|
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 {
|
2023-07-09 12:52:38 +02:00
|
|
|
timespec *ts = nullptr;
|
|
|
|
|
timespec timeout;
|
|
|
|
|
if (uaddr2 != nullptr) {
|
|
|
|
|
auto result = ureadTimespec(timeout, (ptr<timespec>)uaddr2);
|
|
|
|
|
if (result != ErrorCode{}) {
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ts = &timeout;
|
|
|
|
|
}
|
2023-07-10 12:58:53 +02:00
|
|
|
std::uint64_t usec = 0;
|
|
|
|
|
auto start = std::chrono::steady_clock::now();
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2023-07-09 12:52:38 +02:00
|
|
|
|
2023-07-10 12:58:53 +02:00
|
|
|
switch (op) {
|
|
|
|
|
case 0: {
|
|
|
|
|
return with_timeout([&](std::uint64_t ut) {
|
|
|
|
|
return umtx_lock_umtx(thread, (ptr<umtx>)obj, val, ut);
|
|
|
|
|
});
|
2023-07-09 12:52:38 +02:00
|
|
|
}
|
2023-07-08 01:50:45 +02:00
|
|
|
case 1:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_unlock_umtx(thread, (ptr<umtx>)obj, val);
|
|
|
|
|
case 2: {
|
2023-07-10 12:58:53 +02:00
|
|
|
return with_timeout(
|
|
|
|
|
[&](std::uint64_t ut) { return umtx_wait(thread, obj, val, ut); });
|
2023-07-09 12:52:38 +02:00
|
|
|
}
|
2023-07-08 01:50:45 +02:00
|
|
|
case 3:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_wake(thread, obj, val);
|
2023-07-08 01:50:45 +02:00
|
|
|
case 4:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_trylock_umutex(thread, (ptr<umutex>)obj);
|
|
|
|
|
case 5: {
|
2023-07-10 12:58:53 +02:00
|
|
|
return with_timeout([&](std::uint64_t ut) {
|
|
|
|
|
return umtx_lock_umutex(thread, (ptr<umutex>)obj, ut);
|
|
|
|
|
});
|
2023-07-09 12:52:38 +02:00
|
|
|
}
|
2023-07-08 01:50:45 +02:00
|
|
|
case 6:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_unlock_umutex(thread, (ptr<umutex>)obj);
|
2023-07-08 01:50:45 +02:00
|
|
|
case 7:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_set_ceiling(thread, (ptr<umutex>)obj, val,
|
|
|
|
|
(ptr<uint32_t>)uaddr1);
|
|
|
|
|
|
|
|
|
|
case 8: {
|
2023-07-10 12:58:53 +02:00
|
|
|
return with_timeout([&](std::uint64_t ut) {
|
|
|
|
|
return umtx_cv_wait(thread, (ptr<ucond>)obj, (ptr<umutex>)uaddr1, ut,
|
|
|
|
|
val);
|
|
|
|
|
});
|
2023-07-09 12:52:38 +02:00
|
|
|
}
|
|
|
|
|
|
2023-07-08 01:50:45 +02:00
|
|
|
case 9:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_cv_signal(thread, (ptr<ucond>)obj);
|
2023-07-08 01:50:45 +02:00
|
|
|
case 10:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_cv_broadcast(thread, (ptr<ucond>)obj);
|
|
|
|
|
case 11: {
|
2023-07-10 12:58:53 +02:00
|
|
|
return with_timeout(
|
|
|
|
|
[&](std::uint64_t ut) { return umtx_wait_uint(thread, obj, val, ut); });
|
2023-07-09 12:52:38 +02:00
|
|
|
}
|
2023-07-08 01:50:45 +02:00
|
|
|
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);
|
2023-07-09 12:52:38 +02:00
|
|
|
case 15: {
|
2023-07-10 12:58:53 +02:00
|
|
|
return with_timeout([&](std::uint64_t ut) {
|
|
|
|
|
return umtx_wait_uint_private(thread, obj, val, ut);
|
|
|
|
|
});
|
2023-07-09 12:52:38 +02:00
|
|
|
}
|
2023-07-08 01:50:45 +02:00
|
|
|
case 16:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_wake_private(thread, obj, val);
|
|
|
|
|
case 17: {
|
2023-07-10 12:58:53 +02:00
|
|
|
return with_timeout([&](std::uint64_t ut) {
|
|
|
|
|
return umtx_wait_umutex(thread, (ptr<umutex>)obj, ut);
|
|
|
|
|
});
|
2023-07-09 12:52:38 +02:00
|
|
|
}
|
2023-07-08 01:50:45 +02:00
|
|
|
case 18:
|
|
|
|
|
return umtx_wake_umutex(thread, obj, val, uaddr1, uaddr2);
|
|
|
|
|
case 19:
|
|
|
|
|
return umtx_sem_wait(thread, obj, val, uaddr1, uaddr2);
|
|
|
|
|
case 20:
|
|
|
|
|
return umtx_sem_wake(thread, obj, val, uaddr1, uaddr2);
|
|
|
|
|
case 21:
|
2023-07-09 12:52:38 +02:00
|
|
|
return umtx_nwake_private(thread, obj, val);
|
2023-07-08 01:50:45 +02:00
|
|
|
case 22:
|
|
|
|
|
return umtx_wake2_umutex(thread, obj, val, uaddr1, uaddr2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ErrorCode::INVAL;
|
2023-07-03 13:10:16 +02:00
|
|
|
}
|