[orbis-kernel] Implement umtx_wake_umutex

This commit is contained in:
Ivan Chikish 2023-07-10 19:48:37 +03:00
parent 51150f4b07
commit 9a3054a5d1
4 changed files with 32 additions and 15 deletions

View file

@ -38,6 +38,8 @@ struct UmtxChain {
std::pair<const UmtxKey, UmtxCond> *enqueue(UmtxKey &key, Thread *thr);
void erase(std::pair<const UmtxKey, UmtxCond> *obj);
void notify_one(const UmtxKey &key);
void notify_all(const UmtxKey &key);
};
class alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__) KernelContext final {

View file

@ -86,8 +86,7 @@ ErrorCode umtx_wait_uint_private(Thread *thread, ptr<void> addr, ulong id,
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, 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_wake_umutex(Thread *thread, ptr<umutex> m);
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,

View file

@ -15,13 +15,13 @@ static orbis::ErrorCode ureadTimespec(orbis::timespec &ts,
}
orbis::SysResult orbis::sys__umtx_lock(Thread *thread, ptr<umtx> umtx) {
ORBIS_LOG_TODO(__FUNCTION__, umtx);
ORBIS_LOG_TRACE(__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);
ORBIS_LOG_TRACE(__FUNCTION__, umtx);
if (reinterpret_cast<std::uintptr_t>(umtx) - 0x10000 > 0xff'fffe'ffff)
return ErrorCode::FAULT;
return umtx_unlock_umtx(thread, umtx, thread->tid);
@ -29,7 +29,7 @@ orbis::SysResult orbis::sys__umtx_unlock(Thread *thread, ptr<umtx> umtx) {
orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
ulong val, ptr<void> uaddr1,
ptr<void> uaddr2) {
ORBIS_LOG_TODO(__FUNCTION__, obj, op, val, uaddr1, uaddr2);
ORBIS_LOG_TRACE(__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 {
@ -127,7 +127,7 @@ orbis::SysResult orbis::sys__umtx_op(Thread *thread, ptr<void> obj, sint op,
});
}
case 18:
return umtx_wake_umutex(thread, obj, val, uaddr1, uaddr2);
return umtx_wake_umutex(thread, (ptr<umutex>)obj);
case 19:
return umtx_sem_wait(thread, obj, val, uaddr1, uaddr2);
case 20:

View file

@ -27,6 +27,13 @@ void UmtxChain::erase(std::pair<const UmtxKey, UmtxCond> *obj) {
}
}
}
void UmtxChain::notify_one(const UmtxKey &key) {
auto it = sleep_queue.find(key);
it->second.thr = nullptr;
it->second.cv.notify_one(mtx);
this->erase(&*it);
}
} // namespace orbis
orbis::ErrorCode orbis::umtx_lock_umtx(Thread *thread, ptr<umtx> umtx, ulong id,
@ -145,10 +152,7 @@ static ErrorCode do_unlock_normal(Thread *thread, ptr<umutex> m, uint flags) {
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);
chain.notify_one(key);
if (!ok)
return ErrorCode::INVAL;
return {};
@ -285,11 +289,23 @@ orbis::ErrorCode orbis::umtx_wait_umutex(Thread *thread, ptr<umutex> m,
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_wake_umutex(Thread *thread, ptr<umutex> m) {
ORBIS_LOG_TRACE(__FUNCTION__, m);
int owner = m->owner.load(std::memory_order::acquire);
if ((owner & ~kUmutexContested) != 0)
return {};
[[maybe_unused]] uint flags = uread(&m->flags);
auto [chain, key, lock] = g_context.getUmtxChain1(thread->tproc->pid, m);
std::size_t count = chain.sleep_queue.count(key);
if (count <= 1) {
owner = kUmutexContested;
m->owner.compare_exchange_strong(owner, kUmutexUnowned);
}
if (count != 0 && (owner & ~kUmutexContested) == 0)
chain.notify_one(key);
return {};
}
orbis::ErrorCode orbis::umtx_sem_wait(Thread *thread, ptr<void> obj,