From 1bf88f6fe869619322c29d80cec0b6a1348f4e39 Mon Sep 17 00:00:00 2001 From: Ivan Chikish Date: Thu, 20 Jul 2023 15:10:38 +0300 Subject: [PATCH] [orbis-kernel] Make evf IPC-safe --- orbis-kernel/include/orbis/evf.hpp | 8 +--- orbis-kernel/include/orbis/thread/Thread.hpp | 4 +- orbis-kernel/src/evf.cpp | 46 ++++++++------------ orbis-kernel/src/sys/sys_sce.cpp | 10 +++-- 4 files changed, 29 insertions(+), 39 deletions(-) diff --git a/orbis-kernel/include/orbis/evf.hpp b/orbis-kernel/include/orbis/evf.hpp index 8ad5bce46..e8bcc2537 100644 --- a/orbis-kernel/include/orbis/evf.hpp +++ b/orbis-kernel/include/orbis/evf.hpp @@ -32,9 +32,6 @@ struct EventFlag final { struct WaitingThread { Thread *thread; - utils::shared_cv *cv; - std::uint64_t *patternSet; - bool *isCanceled; std::uint64_t bitPattern; std::uint8_t waitMode; @@ -70,10 +67,9 @@ struct EventFlag final { : attrs(attrs), value(initPattern) {} ErrorCode wait(Thread *thread, std::uint8_t waitMode, - std::uint64_t bitPattern, std::uint64_t *patternSet, - std::uint32_t *timeout); + std::uint64_t bitPattern, std::uint32_t *timeout); ErrorCode tryWait(Thread *thread, std::uint8_t waitMode, - std::uint64_t bitPattern, std::uint64_t *patternSet); + std::uint64_t bitPattern); std::size_t notify(NotifyType type, std::uint64_t bits); std::size_t destroy() { return notify(NotifyType::Destroy, {}); } diff --git a/orbis-kernel/include/orbis/thread/Thread.hpp b/orbis-kernel/include/orbis/thread/Thread.hpp index edc8b2af4..1a0bb016c 100644 --- a/orbis-kernel/include/orbis/thread/Thread.hpp +++ b/orbis-kernel/include/orbis/thread/Thread.hpp @@ -4,13 +4,15 @@ #include "orbis-config.hpp" #include "types.hpp" +#include "../utils/SharedCV.hpp" #include "../utils/SharedMutex.hpp" #include namespace orbis { struct Process; struct Thread { - shared_mutex mtx; + utils::shared_mutex mtx; + utils::shared_cv sync_cv; Process *tproc = nullptr; uint64_t retval[2]{}; void *context{}; diff --git a/orbis-kernel/src/evf.cpp b/orbis-kernel/src/evf.cpp index 240bd0aa7..ba035ab14 100644 --- a/orbis-kernel/src/evf.cpp +++ b/orbis-kernel/src/evf.cpp @@ -6,12 +6,7 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode, std::uint64_t bitPattern, - std::uint64_t *patternSet, std::uint32_t *timeout) { - utils::shared_cv cv; - - bool isCanceled = false; - using namespace std::chrono; steady_clock::time_point start{}; @@ -34,29 +29,27 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode, *timeout = 0; }; + // Use retval to pass information between threads + thread->retval[0] = 0; // resultPattern + thread->retval[1] = 0; // isCanceled + std::unique_lock lock(queueMtx); while (true) { if (isDeleted) { return ErrorCode::ACCES; } - if (isCanceled) { + if (thread->retval[1]) { return ErrorCode::CANCELED; } - auto waitingThread = WaitingThread{.thread = thread, - .cv = &cv, - .patternSet = patternSet, - .isCanceled = &isCanceled, - .bitPattern = bitPattern, - .waitMode = waitMode}; + auto waitingThread = WaitingThread{ + .thread = thread, .bitPattern = bitPattern, .waitMode = waitMode}; if (auto patValue = value.load(std::memory_order::relaxed); waitingThread.test(patValue)) { auto resultValue = waitingThread.applyClear(patValue); value.store(resultValue, std::memory_order::relaxed); - if (patternSet != nullptr) { - *patternSet = resultValue; - } + thread->retval[0] = resultValue; // Success break; } @@ -90,21 +83,21 @@ orbis::ErrorCode orbis::EventFlag::wait(Thread *thread, std::uint8_t waitMode, waitingThreads[position] = waitingThread; if (timeout) { - cv.wait(queueMtx, *timeout); + thread->sync_cv.wait(queueMtx, *timeout); update_timeout(); continue; } - cv.wait(queueMtx); + thread->sync_cv.wait(queueMtx); } // TODO: update thread state return {}; } -orbis::ErrorCode orbis::EventFlag::tryWait(Thread *, std::uint8_t waitMode, - std::uint64_t bitPattern, - std::uint64_t *patternSet) { +orbis::ErrorCode orbis::EventFlag::tryWait(Thread *thread, + std::uint8_t waitMode, + std::uint64_t bitPattern) { writer_lock lock(queueMtx); if (isDeleted) { @@ -118,10 +111,7 @@ orbis::ErrorCode orbis::EventFlag::tryWait(Thread *, std::uint8_t waitMode, waitingThread.test(patValue)) { auto resultValue = waitingThread.applyClear(patValue); value.store(resultValue, std::memory_order::relaxed); - if (patternSet != nullptr) { - *patternSet = resultValue; - } - + thread->retval[0] = resultValue; return {}; } @@ -146,16 +136,14 @@ std::size_t orbis::EventFlag::notify(NotifyType type, std::uint64_t bits) { auto resultValue = thread->applyClear(patValue); patValue = resultValue; - if (thread->patternSet != nullptr) { - *thread->patternSet = resultValue; - } + thread->thread->retval[0] = resultValue; if (type == NotifyType::Cancel) { - *thread->isCanceled = true; + thread->thread->retval[1] = true; } // TODO: update thread state // release wait on waiter thread - thread->cv->notify_one(queueMtx); + thread->thread->sync_cv.notify_one(queueMtx); waitingThreadsCount.fetch_sub(1, std::memory_order::relaxed); std::memmove(thread, thread + 1, diff --git a/orbis-kernel/src/sys/sys_sce.cpp b/orbis-kernel/src/sys/sys_sce.cpp index 75deaa4bb..539d8dda2 100644 --- a/orbis-kernel/src/sys/sys_sce.cpp +++ b/orbis-kernel/src/sys/sys_sce.cpp @@ -209,8 +209,8 @@ orbis::SysResult orbis::sys_evf_wait(Thread *thread, sint id, std::uint32_t resultTimeout{}; std::uint64_t resultPattern{}; auto result = evf->wait(thread, mode, patternSet, - pPatternSet != nullptr ? &resultPattern : nullptr, pTimeout != nullptr ? &resultTimeout : nullptr); + resultPattern = thread->retval[0]; ORBIS_LOG_NOTICE("sys_evf_wait wakeup", thread, resultPattern, resultTimeout); @@ -221,6 +221,9 @@ orbis::SysResult orbis::sys_evf_wait(Thread *thread, sint id, if (pTimeout != nullptr) { uwrite(pTimeout, (uint32_t)resultTimeout); } + + thread->retval[0] = 0; + thread->retval[1] = 0; return result; } @@ -242,13 +245,14 @@ orbis::SysResult orbis::sys_evf_trywait(Thread *thread, sint id, } std::uint64_t resultPattern{}; - auto result = evf->tryWait(thread, mode, patternSet, - pPatternSet != nullptr ? &resultPattern : nullptr); + auto result = evf->tryWait(thread, mode, patternSet); + resultPattern = thread->retval[0]; if (pPatternSet != nullptr) { uwrite(pPatternSet, (uint64_t)resultPattern); } + thread->retval[0] = 0; return result; } orbis::SysResult orbis::sys_evf_set(Thread *thread, sint id, uint64_t value) {