mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-01-20 15:40:30 +01:00
[orbis-kernel] evf: fix set data race, Multi mode fixes
This commit is contained in:
parent
0d7b090032
commit
cd9ced41d8
|
|
@ -61,6 +61,12 @@ struct EventFlag {
|
|||
|
||||
shared_mutex queueMtx;
|
||||
|
||||
enum class NotifyType {
|
||||
Set,
|
||||
Cancel,
|
||||
Destroy
|
||||
};
|
||||
|
||||
explicit EventFlag(std::int32_t attrs) : attrs(attrs) {}
|
||||
|
||||
ErrorCode wait(Thread *thread, std::uint8_t waitMode,
|
||||
|
|
@ -68,33 +74,23 @@ struct EventFlag {
|
|||
std::uint32_t *timeout);
|
||||
ErrorCode tryWait(Thread *thread, std::uint8_t waitMode,
|
||||
std::uint64_t bitPattern, std::uint64_t *patternSet);
|
||||
std::size_t notify(bool isCancel = false, std::uint64_t cancelValue = 0);
|
||||
std::size_t notify(NotifyType type, std::uint64_t bits);
|
||||
|
||||
std::size_t destroy() {
|
||||
isDeleted = true;
|
||||
return notify();
|
||||
return notify(NotifyType::Destroy, {});
|
||||
}
|
||||
|
||||
std::size_t cancel(std::uint64_t value) {
|
||||
return notify(true, value);
|
||||
return notify(NotifyType::Cancel, value);
|
||||
}
|
||||
|
||||
std::size_t set(std::uint64_t bits) {
|
||||
{
|
||||
writer_lock lock(queueMtx);
|
||||
value.fetch_or(bits, std::memory_order::relaxed);
|
||||
}
|
||||
|
||||
return notify();
|
||||
return notify(NotifyType::Set, bits);
|
||||
}
|
||||
|
||||
void clear(std::uint64_t bits) {
|
||||
{
|
||||
writer_lock lock(queueMtx);
|
||||
value.fetch_and(bits, std::memory_order::relaxed);
|
||||
}
|
||||
|
||||
value &= bits;
|
||||
writer_lock lock(queueMtx);
|
||||
value.fetch_and(bits, std::memory_order::relaxed);
|
||||
}
|
||||
|
||||
void incRef() { references.fetch_add(1, std::memory_order::relaxed); }
|
||||
|
|
|
|||
|
|
@ -109,13 +109,19 @@ orbis::ErrorCode orbis::EventFlag::tryWait(Thread *,
|
|||
return ErrorCode::BUSY;
|
||||
}
|
||||
|
||||
std::size_t orbis::EventFlag::notify(bool isCancel, std::uint64_t cancelValue) {
|
||||
std::size_t orbis::EventFlag::notify(NotifyType type, std::uint64_t bits) {
|
||||
writer_lock lock(queueMtx);
|
||||
auto count = waitingThreadsCount.load(std::memory_order::relaxed);
|
||||
auto patValue = value.load(std::memory_order::relaxed);
|
||||
|
||||
if (type == NotifyType::Destroy) {
|
||||
isDeleted = true;
|
||||
} else if (type == NotifyType::Set) {
|
||||
patValue |= bits;
|
||||
}
|
||||
|
||||
auto testThread = [&](WaitingThread *thread) {
|
||||
if (!isCancel && !isDeleted && !thread->test(patValue)) {
|
||||
if (type != NotifyType::Set && !thread->test(patValue)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -124,18 +130,16 @@ std::size_t orbis::EventFlag::notify(bool isCancel, std::uint64_t cancelValue) {
|
|||
if (thread->patternSet != nullptr) {
|
||||
*thread->patternSet = resultValue;
|
||||
}
|
||||
if (isCancel) {
|
||||
if (type == NotifyType::Cancel) {
|
||||
*thread->isCanceled = true;
|
||||
} else {
|
||||
value.store(resultValue, std::memory_order::relaxed);
|
||||
}
|
||||
|
||||
// TODO: update thread state
|
||||
thread->mtx->unlock(); // release wait on waiter thread
|
||||
|
||||
waitingThreadsCount.fetch_sub(1, std::memory_order::relaxed);
|
||||
std::memmove(thread, thread + 1, (waitingThreads + count - (thread + 1)) * sizeof(*waitingThreads));
|
||||
--count;
|
||||
std::memmove(thread, thread + 1, waitingThreads + count - (thread + 1));
|
||||
return true;
|
||||
};
|
||||
|
||||
|
|
@ -160,8 +164,10 @@ std::size_t orbis::EventFlag::notify(bool isCancel, std::uint64_t cancelValue) {
|
|||
}
|
||||
}
|
||||
|
||||
if (isCancel) {
|
||||
value.store(cancelValue, std::memory_order::relaxed);
|
||||
if (type == NotifyType::Cancel) {
|
||||
value.store(bits, std::memory_order::relaxed);
|
||||
} else {
|
||||
value.store(patValue, std::memory_order::relaxed);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue