mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-02-16 12:45:29 +01:00
[orbis-kernel] Make evf IPC-safe
This commit is contained in:
parent
72185f0086
commit
1bf88f6fe8
|
|
@ -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, {}); }
|
||||
|
|
|
|||
|
|
@ -4,13 +4,15 @@
|
|||
#include "orbis-config.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
#include "../utils/SharedCV.hpp"
|
||||
#include "../utils/SharedMutex.hpp"
|
||||
#include <thread>
|
||||
|
||||
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{};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue