[orbis-kernel] Implement umtx_cv_signal/broadcast

This commit is contained in:
Ivan Chikish 2023-07-11 08:48:12 +03:00
parent e01dfbfbe7
commit eda542561c
2 changed files with 22 additions and 7 deletions

View file

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

View file

@ -28,13 +28,21 @@ void UmtxChain::erase(std::pair<const UmtxKey, UmtxCond> *obj) {
} }
} }
void UmtxChain::notify_one(const UmtxKey &key) { uint UmtxChain::notify_one(const UmtxKey &key) {
auto it = sleep_queue.find(key); auto it = sleep_queue.find(key);
if (it == sleep_queue.end()) if (it == sleep_queue.end())
return; return 0;
it->second.thr = nullptr; it->second.thr = nullptr;
it->second.cv.notify_one(mtx); it->second.cv.notify_one(mtx);
this->erase(&*it); this->erase(&*it);
return 1;
}
uint UmtxChain::notify_all(const UmtxKey &key) {
uint n = 0;
while (notify_one(key))
n++;
return n;
} }
} // namespace orbis } // namespace orbis
@ -302,12 +310,19 @@ orbis::ErrorCode orbis::umtx_cv_wait(Thread *thread, ptr<ucond> cv,
} }
orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr<ucond> cv) { orbis::ErrorCode orbis::umtx_cv_signal(Thread *thread, ptr<ucond> cv) {
ORBIS_LOG_TODO(__FUNCTION__, cv); ORBIS_LOG_NOTICE(__FUNCTION__, cv);
return ErrorCode::NOSYS; auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, cv);
std::size_t count = chain.sleep_queue.count(key);
if (chain.notify_one(key) >= count)
cv->has_waiters.store(0, std::memory_order::relaxed);
return {};
} }
orbis::ErrorCode orbis::umtx_cv_broadcast(Thread *thread, ptr<ucond> cv) { orbis::ErrorCode orbis::umtx_cv_broadcast(Thread *thread, ptr<ucond> cv) {
ORBIS_LOG_TODO(__FUNCTION__, cv); ORBIS_LOG_NOTICE(__FUNCTION__, cv);
auto [chain, key, lock] = g_context.getUmtxChain0(thread->tproc->pid, cv);
chain.notify_all(key);
cv->has_waiters.store(0, std::memory_order::relaxed);
return ErrorCode::NOSYS; return ErrorCode::NOSYS;
} }