rpcsx/orbis-kernel/include/orbis/evf.hpp
DH e90566e7de [rpcsx-os/orbis-kernel] random fixes
fix pipe
fix socketpair
fix bridge
fix evf_wait with timeout
fix umtx_op(0x17)
implement ipmi evf
stub sched_get_priority_max/min
stub sys_rtprio_thread
implement sys_yield
emit event on signal
stub ajm register/unregister ioctls
stub av_control ioctl
hack removal
2024-01-04 03:53:58 +03:00

95 lines
2.3 KiB
C++

#pragma once
#include "KernelAllocator.hpp"
#include "thread/Thread.hpp"
#include "utils/SharedMutex.hpp"
#include <atomic>
namespace orbis {
enum {
kEvfAttrThFifo = 0x01,
kEvfAttrThPrio = 0x02,
kEvfAttrSingle = 0x10,
kEvfAttrMulti = 0x20,
kEvfAttrShared = 0x100,
};
enum {
kEvfWaitModeAnd = 0x01,
kEvfWaitModeOr = 0x02,
kEvfWaitModeClearAll = 0x10,
kEvfWaitModeClearPat = 0x20,
};
struct EventFlag final {
char name[32];
bool isDeleted = false;
std::uint8_t attrs = kEvfAttrMulti | kEvfAttrThFifo;
std::atomic<unsigned> references{0};
std::atomic<std::uint64_t> value{0};
struct WaitingThread {
Thread *thread;
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;
}
return (value & bitPattern) != 0;
}
std::uint64_t applyClear(std::uint64_t value) {
if (waitMode & kEvfWaitModeClearAll) {
return 0;
}
if (waitMode & kEvfWaitModeClearPat) {
return value & ~bitPattern;
}
return value;
}
};
utils::shared_mutex queueMtx;
utils::kvector<WaitingThread> waitingThreads;
enum class NotifyType { Set, Cancel, Destroy };
EventFlag() = default;
EventFlag(std::int32_t attrs, std::uint64_t initPattern)
: attrs(attrs), value(initPattern) {}
ErrorCode wait(Thread *thread, std::uint8_t waitMode,
std::uint64_t bitPattern, std::uint32_t *timeout);
ErrorCode tryWait(Thread *thread, std::uint8_t waitMode,
std::uint64_t bitPattern);
std::size_t notify(NotifyType type, std::uint64_t bits);
std::size_t destroy() { return notify(NotifyType::Destroy, {}); }
std::size_t cancel(std::uint64_t value) {
return notify(NotifyType::Cancel, value);
}
std::size_t set(std::uint64_t bits) { return notify(NotifyType::Set, bits); }
void clear(std::uint64_t bits) {
writer_lock lock(queueMtx);
value.fetch_and(bits, std::memory_order::relaxed);
}
void incRef() { references.fetch_add(1, std::memory_order::relaxed); }
void decRef() {
if (references.fetch_sub(1, std::memory_order::relaxed) == 1) {
kdelete(this);
}
}
};
} // namespace orbis