2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/Scheduler.h"
4#include "pedigree/kernel/process/TerminationDeferral.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/syscallError.h"
7#include "pedigree/kernel/time/Time.h"
8#include "pedigree/kernel/utilities/List.h"
12#include "PosixProcess.h"
13#include "PosixSubsystem.h"
14#include "linux-wait-abi.h"
15#include "queued-signal.h"
24constexpr size_t PendingLimit = 16;
25constexpr uint64_t Unblockable = (uint64_t(1) << (SIGKILL - 1)) | (uint64_t(1) << (SIGSTOP - 1));
28 return process && process->getType() == Process::Posix
36 MemoryCopy(&result, info.bytes + offset,
sizeof(result));
41 MemoryCopy(info.bytes + offset, &value,
sizeof(value));
44void cancelSource(
Process* process,
const void* source) {
48 thread->cullSignalSource(source);
59 const size_t previous = __atomic_fetch_sub(&m_Quota->count,
size_t(1), __ATOMIC_ACQ_REL);
65 UserQuota* quota =
nullptr;
66 for (
auto it = quotas.
begin(); it != quotas.
end();) {
67 UserQuota* candidate = *it;
68 if (candidate->uid == uid) {
71 }
else if (!__atomic_load_n(&candidate->count, __ATOMIC_ACQUIRE)) {
72 it = quotas.
erase(it);
79 quota =
new UserQuota{uid, 0};
82 if (__atomic_load_n("a->count, __ATOMIC_ACQUIRE) >= PendingLimit) {
83 SYSCALL_ERROR(NoMoreProcesses);
86 __atomic_add_fetch("a->count,
size_t(1), __ATOMIC_ACQ_REL);
97 : m_Reservation(reservation), m_Generation(0), m_Done(
false) {}
99 : m_Token(token), m_Generation(0), m_Done(
false) {
101 m_Generation = token->m_Generation;
103 bool active()
const override {
107 return m_Token->m_Active && m_Token->m_Generation == m_Generation;
109 bool timer()
const override {
110 return bool(m_Token);
112 const void* source()
const override {
113 return m_Token.
get();
115 void timerInfo(int32_t&
id, int32_t& overrun)
const override {
119 id = m_Token->timerId;
120 const uint64_t count = m_Token->m_Expirations;
121 overrun = count > 0x80000000ULL ? 0x7fffffff : (count ? count - 1 : 0);
123 void complete(
bool delivered, int32_t overrun)
override {
131 m_Reservation.
reset();
135 if (!m_Token->m_Active || m_Token->m_Generation != m_Generation)
138 const uint64_t consumed = uint64_t(overrun) + 1;
139 m_Token->m_Expirations =
140 m_Token->m_Expirations > consumed ? m_Token->m_Expirations - consumed : 0;
141 m_Token->m_DeliveredOverrun = overrun;
142 }
else if (overrun >= 0) {
144 m_Token->m_Expirations = 0;
146 m_Token->m_Pending =
false;
152 uint64_t m_Generation;
158 auto reservation = SignalQueueReservation::reserve(process);
163PosixTimerSignalToken::PosixTimerSignalToken()
169 m_DeliveredOverrun(0) {}
170PosixTimerSignalToken::~PosixTimerSignalToken() =
default;
171bool PosixTimerSignalToken::addExpirations(uint64_t count) {
175 m_Expirations = count > ~uint64_t(0) - m_Expirations ? ~uint64_t(0) : m_Expirations + count;
176 if (!m_Expirations || m_Pending)
181void PosixTimerSignalToken::queueFailed() {
185int PosixTimerSignalToken::getDeliveredOverrun() {
187 return m_DeliveredOverrun;
190 auto reservation = SignalQueueReservation::reserve(process);
194 token->m_Reservation = reservation;
197int posix_signal_queue_timer(
Process* process,
Thread* target,
int signal, uint64_t value,
199 auto* owner = subsystem(process);
201 const bool processDirected = !target;
205 target = selected.get();
208 owner->queueSignalDelivery(target, signal,
nullptr, -2, processDirected, value, state);
209 if (result == PosixSubsystem::SignalDeliveryResult::Ignored)
210 state->complete(
false, 0);
211 return result == PosixSubsystem::SignalDeliveryResult::Queued ||
212 result == PosixSubsystem::SignalDeliveryResult::Ignored
217 auto* owner = subsystem(process);
218 if (!owner || !token)
224 ++token->m_Generation;
225 token->m_Expirations = 0;
226 token->m_DeliveredOverrun = 0;
227 token->m_Pending =
false;
229 cancelSource(process, token.
get());
230 owner->pendingSignalContext()->recordChange();
232void posix_signal_cancel_timer(
Process* process,
234 auto* owner = subsystem(process);
235 if (!owner || !token)
241 token->m_Active =
false;
242 ++token->m_Generation;
243 token->m_Expirations = 0;
244 token->m_Pending =
false;
246 cancelSource(process, token.
get());
247 token->m_Reservation.
reset();
248 owner->pendingSignalContext()->recordChange();
251int posix_rt_sigpending(uint64_t* signals,
size_t size) {
252 if (size !=
sizeof(uint64_t)) {
253 SYSCALL_ERROR(InvalidArgument);
258 auto* owner = subsystem(process);
260 uint64_t mask = current->pendingSignalMask();
263 if (process->
acquireThread(thread, i - 1) && thread.get() != current)
264 mask |= thread->pendingSignalMask(
true);
268 SYSCALL_ERROR(BadAddress);
277 if (size !=
sizeof(uint64_t)) {
278 SYSCALL_ERROR(InvalidArgument);
285 SYSCALL_ERROR(BadAddress);
289 (requested.tv_sec < 0 || requested.tv_nsec < 0 || requested.tv_nsec >= 1000000000)) {
290 SYSCALL_ERROR(InvalidArgument);
293 Time::Timestamp remaining = Time::Infinity;
295 const uint64_t maximum = Time::Infinity - 1;
296 remaining = uint64_t(requested.tv_sec) > (maximum - requested.tv_nsec) / 1000000000
298 : uint64_t(requested.tv_sec) * 1000000000 + requested.tv_nsec;
300 mask &= ~Unblockable;
303 auto* owner = subsystem(process);
306 current->setSynchronousSignalMask(mask);
310 thread->setSynchronousSignalMask(0);
312 } enrollment{current};
315 if (reservation.reserve(current, mask)) {
318 posix_signal_record_siginfo(record, result);
320 SYSCALL_ERROR(BadAddress);
323 reservation.commit(record.overrun);
324 return record.number;
327 SYSCALL_ERROR(NoMoreProcesses);
330 if (current->hasEvents()) {
331 SYSCALL_ERROR(Interrupted);
334 ConditionVariable::Error error = ConditionVariable::NoError;
335 if (!owner->pendingSignalChanged().wait(owner->pendingSignalLock(), remaining, error)) {
338 if (error == ConditionVariable::TimedOut)
339 SYSCALL_ERROR(NoMoreProcesses);
341 SYSCALL_ERROR(Interrupted);
349 if (pid <= 0 || signal <= 0 || signal > 64) {
350 SYSCALL_ERROR(InvalidArgument);
355 SYSCALL_ERROR(BadAddress);
360 if (field<int32_t>(supplied, 8) != -1) {
361 SYSCALL_ERROR(InvalidArgument);
365 if (!
Scheduler::instance().acquireProcessByUserspaceId(target, pid) || !subsystem(target.get())) {
366 SYSCALL_ERROR(NoSuchProcess);
371 auto* recipient =
static_cast<PosixProcess*
>(target.get());
372 const int64_t real = caller->
getUserId(), effective = caller->getEffectiveUserId();
373 const int64_t targetReal = recipient->getUserId(), saved = recipient->getSavedUserId();
374 if (effective != 0 &&
375 !((real >= 0 && (real == targetReal || real == saved)) ||
376 (effective >= 0 && (effective == targetReal || effective == saved))) &&
377 !(signal == SIGCONT && caller->sharesSession(*recipient))) {
378 SYSCALL_ERROR(NotEnoughPermissions);
382 if (!recipient->acquireProcessSignalThread(thread)) {
383 SYSCALL_ERROR(NoSuchProcess);
386 const auto result = subsystem(recipient)->queueSignalDelivery(
387 thread.get(), signal,
nullptr, -1,
true, field<uint64_t>(supplied, 24));
388 if (result == PosixSubsystem::SignalDeliveryResult::Full)
390 if (result == PosixSubsystem::SignalDeliveryResult::Unavailable ||
391 result == PosixSubsystem::SignalDeliveryResult::Rejected) {
392 SYSCALL_ERROR(NoSuchProcess);
static bool mutexAcquired(Error error)
int64_t getUserId() const final
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)
MUST_USE_RESULT bool acquireProcessSignalThread(ThreadLease &lease)
MUST_USE_RESULT bool acquireThread(ThreadLease &lease, size_t n)
virtual int64_t getUserId() const
static ProcessorInformation & information()
static Scheduler & instance()
Process * getParent() const
Iterator erase(Iterator &Iter)
void pushBack(const T &value)