9#include "eventfd-syscalls.h"
10#include "pedigree/kernel/LockGuard.h"
11#include "pedigree/kernel/syscallError.h"
12#include "pedigree/kernel/utilities/SharedPointer.h"
13#include "pedigree/kernel/utilities/assert.h"
17#include "modules/subsys/posix/FileDescriptor.h"
18#include "modules/subsys/posix/PosixSubsystem.h"
21constexpr uint64_t MaximumCounter = ~static_cast<uint64_t>(0) - 1;
23void setWaitError(ConditionVariable::Error error) {
24 if (error == ConditionVariable::Interrupted || error == ConditionVariable::TerminationDeferred) {
25 SYSCALL_ERROR(Interrupted);
27 SYSCALL_ERROR(BadFileDescriptor);
32EventFd::EventFd(uint64_t initialValue,
bool semaphoreMode)
37 m_Counter(initialValue),
40 m_DescriptorOwners(0),
41 m_SemaphoreMode(semaphoreMode),
42 m_DescriptorAdmissionOpen(true) {}
45 assert(!m_DescriptorOwners);
54 SYSCALL_ERROR(NoMoreProcesses);
58 ConditionVariable::Error error = ConditionVariable::NoError;
59 if (!m_Readers.
wait(m_Lock, error)) {
68 const bool wasWritable = m_Counter < MaximumCounter;
69 if (m_SemaphoreMode) {
77 ++m_Generations.write;
83 return static_cast<int>(
sizeof(value));
87 if (value == ~
static_cast<uint64_t
>(0)) {
88 SYSCALL_ERROR(InvalidArgument);
93 while (value > MaximumCounter - m_Counter) {
96 SYSCALL_ERROR(NoMoreProcesses);
100 ConditionVariable::Error error = ConditionVariable::NoError;
101 if (!m_Writers.
wait(m_Lock, error)) {
110 const bool wasReadable = m_Counter != 0;
112 if (!wasReadable && m_Counter) {
113 ++m_Generations.read;
115 m_WriteGeneration += 1;
120 return static_cast<int>(
sizeof(value));
125 ReadyMask ready = ReadyNone;
129 if (m_Counter < MaximumCounter) {
137 return m_Generations;
141 return m_WriteGeneration.value();
146 if (!m_DescriptorAdmissionOpen) {
149 ++m_DescriptorOwners;
153void EventFd::removeDescriptorOwner() {
155 assert(m_DescriptorOwners);
156 --m_DescriptorOwners;
157 if (!m_DescriptorOwners) {
158 m_DescriptorAdmissionOpen =
false;
162int posix_eventfd(
unsigned int initialValue) {
163 return posix_eventfd2(initialValue, 0);
166int posix_eventfd2(
unsigned int initialValue,
int flags) {
167 constexpr int AllowedFlags =
168 LinuxEventFd::Semaphore | LinuxEventFd::NonBlock | LinuxEventFd::CloseOnExec;
169 if (flags & ~AllowedFlags) {
170 SYSCALL_ERROR(InvalidArgument);
174 const size_t fd = getAvailableDescriptor();
175 const int descriptorFlags = flags & LinuxEventFd::CloseOnExec ? FD_CLOEXEC : 0;
176 const int statusFlags = O_RDWR | (flags & LinuxEventFd::NonBlock ? O_NONBLOCK : 0);
180 addDescriptor(
static_cast<int>(fd), descriptor);
181 return static_cast<int>(fd);
MUST_USE_RESULT bool wait(Mutex &mutex, Time::Timestamp &timeout, Error &error, WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
static bool mutexAcquired(Error error)
uint64_t writeGeneration() const
ReadinessGenerations readinessGenerations() override
int readValue(uint64_t &value, bool canBlock)
int writeValue(uint64_t value, bool canBlock)
MUST_USE_RESULT bool addDescriptorOwner()
void setEventFdImpl(const SharedPointer< EventFd > &implementation)
void notifyReadiness(ReadyMask mask)
void closeReadiness(ReadyMask mask=ReadyInvalid|ReadyHangup)
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)