2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/TerminationDeferral.h"
4#include "pedigree/kernel/process/Thread.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/syscallError.h"
10#include "FileDescriptor.h"
11#include "PosixSubsystem.h"
12#include "signalfd-syscalls.h"
15constexpr uint64_t Unblockable = (uint64_t(1) << 8) | (uint64_t(1) << 18);
16constexpr int Nonblock = 0x800, CloseOnExec = 0x80000;
17struct SignalFdRecord {
22 uint32_t timerId, band, overrun, trap;
23 int32_t status, integer;
24 uint64_t pointer, userTime, systemTime, address;
25 uint16_t addressLowBit, padding;
28 uint32_t architecture;
31static_assert(
sizeof(SignalFdRecord) == 128,
"Linux signalfd_siginfo layout");
32static_assert(__builtin_offsetof(SignalFdRecord, pointer) == 48,
"signalfd pointer offset");
35 SignalFdRecord result = {};
36 result.number = source.number;
37 result.code = source.code;
38 result.pid = source.pid;
39 result.uid = source.uid;
40 if (source.code == -2) {
43 result.timerId = source.timerId;
44 result.overrun = source.overrun;
46 result.integer = source.value;
47 result.pointer = source.value;
48 result.status = source.status;
49 result.userTime = source.userTime;
50 result.systemTime = source.systemTime;
56bool scalarCopy(
void* opaque,
const void* data,
size_t size) {
57 auto& cursor = *
static_cast<ScalarCopy*
>(opaque);
60 cursor.destination += size;
67 explicit SignalFdState(uint64_t mask) : m_Mask(mask & ~Unblockable) {}
68 uint64_t mask()
const {
69 return __atomic_load_n(&m_Mask, __ATOMIC_ACQUIRE);
71 void snapshot(uint64_t& mask, uint64_t& generation) {
74 generation = m_Generation;
77 return __atomic_load_n(&m_Closed, __ATOMIC_ACQUIRE);
79 bool setMask(uint64_t mask) {
83 SYSCALL_ERROR(BadFileDescriptor);
86 __atomic_store_n(&m_Mask, mask & ~Unblockable, __ATOMIC_RELEASE);
87 __atomic_add_fetch(&m_Generation, uint64_t(1), __ATOMIC_RELEASE);
106 __atomic_store_n(&m_Closed,
true, __ATOMIC_RELEASE);
115 uint64_t m_Generation = 0;
117 bool m_Closed =
false;
123 : m_View(view), m_MaskChanged(maskChanged) {}
125 m_View->changed(m_MaskChanged);
136 : m_State(state), m_Context(context), m_Binding(binding) {}
137SignalFdView::~SignalFdView() {
140 m_MaskSubscription.reset();
141 m_PendingSubscription.reset();
144bool SignalFdView::subscribe() {
146 ReadyRead | ReadyHangup,
148 m_PendingSubscription) &&
150 ReadyRead | ReadyHangup,
154void SignalFdView::changed(
bool maskChanged) {
159ReadyMask SignalFdView::queryReady() {
160 if (m_State->closed())
161 return ReadyInvalid | ReadyHangup;
162 return m_Context->query(m_Binding, m_State->mask());
165 return generationsFor(m_Binding);
167ReadyMask SignalFdView::queryCallerReady() {
171 if (m_State->closed())
172 return ReadyInvalid | ReadyHangup;
173 return m_Context->query(binding, m_State->mask());
182 uint64_t mask, maskGeneration;
183 m_State->snapshot(mask, maskGeneration);
185 m_Context->query(binding, mask, &result);
188 if (m_GenerationBinding.
get() != binding.
get() || m_MaskGeneration != maskGeneration ||
189 m_PendingGeneration != result.read) {
190 m_GenerationBinding = binding;
191 m_MaskGeneration = maskGeneration;
192 m_PendingGeneration = result.read;
195 result.read = m_ReadGeneration;
199SignalFd::SignalFd(uint64_t mask) : m_State(new
SignalFdState(mask)) {}
200SignalFd::~SignalFd() =
default;
201bool SignalFd::setMask(uint64_t mask) {
202 return m_State->setMask(mask);
204bool SignalFd::addDescriptorOwner() {
205 return m_State->addOwner();
207void SignalFd::removeDescriptorOwner() {
208 m_State->removeOwner();
213 auto context = owner->pendingSignalContext();
214 auto binding = context->bind(thread);
215 if (!binding || m_State->closed())
218 if (!view->subscribe())
222ssize_t SignalFd::readToUser(
void* destination,
size_t count,
bool canBlock) {
223 ScalarCopy cursor{
static_cast<uint8_t*
>(destination)};
224 return readWithCopy(count, canBlock, scalarCopy, &cursor);
226ssize_t SignalFd::readWithCopy(
size_t count,
bool canBlock, PosixDescriptorReadCopy copy,
229 if (count <
sizeof(SignalFdRecord)) {
230 SYSCALL_ERROR(InvalidArgument);
233 auto view = bindCaller();
235 SYSCALL_ERROR(BadFileDescriptor);
239 auto context = view->m_Context;
243 while (count - copied >=
sizeof(SignalFdRecord)) {
244 if (m_State->closed()) {
249 SYSCALL_ERROR(BadFileDescriptor);
253 if (reservation.reserve(caller, m_State->mask())) {
255 const SignalFdRecord result = encode(record);
256 if (!copy(opaque, &result,
sizeof(result))) {
261 SYSCALL_ERROR(BadAddress);
264 reservation.commit(record.overrun);
265 copied +=
sizeof(result);
273 SYSCALL_ERROR(NoMoreProcesses);
276 if (caller->hasEvents()) {
277 SYSCALL_ERROR(Interrupted);
280 ConditionVariable::Error error = ConditionVariable::NoError;
281 if (!context->changed.wait(context->lock, error)) {
284 SYSCALL_ERROR(Interrupted);
292int posix_signalfd(
int fd,
const uint64_t* mask,
size_t size) {
293 return posix_signalfd4(fd, mask, size, 0);
295int posix_signalfd4(
int fd,
const uint64_t* mask,
size_t size,
int flags) {
296 if (size !=
sizeof(uint64_t) || (flags & ~(Nonblock | CloseOnExec))) {
297 SYSCALL_ERROR(InvalidArgument);
300 uint64_t interest = 0;
302 SYSCALL_ERROR(BadAddress);
307 if (!acquireDescriptor(fd, descriptor)) {
308 SYSCALL_ERROR(BadFileDescriptor);
311 auto signalFd = descriptor->getSignalFdImpl();
313 SYSCALL_ERROR(InvalidArgument);
316 if (!signalFd->setMask(interest))
321 const size_t number = getAvailableDescriptor();
323 new FileDescriptor(
nullptr, 0, number, flags & CloseOnExec ? FD_CLOEXEC : 0,
324 O_RDWR | (flags & Nonblock ? O_NONBLOCK : 0));
326 addDescriptor(number, descriptor);
static bool mutexAcquired(Error error)
static bool copyFromUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static bool copyToUser(void *destination, const void *source, size_t count, size_t elementSize=1)
static ProcessorInformation & information()
void notifyReadiness(ReadyMask mask)
void closeReadiness(ReadyMask mask=ReadyInvalid|ReadyHangup)
MUST_USE_RESULT bool subscribeReadiness(ReadyMask interest, const SharedPointer< ReadinessObserver > &observer, ReadinessSubscription &subscription)
void readinessChanged(ReadyMask) override
ReadinessGenerations readinessGenerations() override
void setErrno(size_t err)
Process * getParent() const