diff --git a/orbis-kernel/include/orbis/evf.hpp b/orbis-kernel/include/orbis/evf.hpp index 441b2c5ba..8403109e5 100644 --- a/orbis-kernel/include/orbis/evf.hpp +++ b/orbis-kernel/include/orbis/evf.hpp @@ -35,6 +35,8 @@ struct EventFlag final { std::uint64_t bitPattern; std::uint8_t waitMode; + bool operator==(const WaitingThread &) const = default; + bool test(std::uint64_t value) const { if (waitMode & kEvfWaitModeAnd) { return (value & bitPattern) == bitPattern; diff --git a/orbis-kernel/src/evf.cpp b/orbis-kernel/src/evf.cpp index 15a8f5b4b..dd3e2fe68 100644 --- a/orbis-kernel/src/evf.cpp +++ b/orbis-kernel/src/evf.cpp @@ -30,16 +30,24 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode, }; thread->evfResultPattern = 0; - thread->evfIsCancelled = 0; + thread->evfIsCancelled = -1; std::unique_lock lock(queueMtx); while (true) { if (isDeleted) { + if (thread->evfIsCancelled == UINT64_MAX) + thread->evfResultPattern = value.load(); return ErrorCode::ACCES; } - if (thread->evfIsCancelled) { + if (thread->evfIsCancelled == 1) { return ErrorCode::CANCELED; } + if (thread->evfIsCancelled == 0) { + break; + } + + thread->evfResultPattern = 0; + thread->evfIsCancelled = -1; auto waitingThread = WaitingThread{ .thread = thread, .bitPattern = bitPattern, .waitMode = waitMode}; @@ -48,12 +56,11 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode, waitingThread.test(patValue)) { auto resultValue = waitingThread.applyClear(patValue); value.store(resultValue, std::memory_order::relaxed); - thread->evfResultPattern = resultValue; + thread->evfResultPattern = patValue; // Success break; - } - - if (timeout && *timeout == 0) { + } else if (timeout && *timeout == 0) { + thread->evfResultPattern = patValue; return ErrorCode::TIMEDOUT; } @@ -72,10 +79,13 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode, if (timeout) { thread->sync_cv.wait(queueMtx, *timeout); update_timeout(); - continue; + } else { + thread->sync_cv.wait(queueMtx); } - thread->sync_cv.wait(queueMtx); + if (thread->evfIsCancelled == UINT64_MAX) { + std::erase(waitingThreads, waitingThread); + } } // TODO: update thread state @@ -98,7 +108,7 @@ orbis::ErrorCode orbis::EventFlag::tryWait(Thread *thread, waitingThread.test(patValue)) { auto resultValue = waitingThread.applyClear(patValue); value.store(resultValue, std::memory_order::relaxed); - thread->evfResultPattern = resultValue; + thread->evfResultPattern = patValue; return {}; }