2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/Scheduler.h"
4#include "pedigree/kernel/process/SignalEvent.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/utilities/lib.h"
8#include "PosixSubsystem.h"
9#include "queued-signal.h"
11void PendingSignalContext::attach(
Process* process) {
13 if (!m_Closed && (!m_Process || m_Process == process))
16void PendingSignalContext::close() {
17 if (__atomic_load_n(&m_Closed, __ATOMIC_ACQUIRE))
21 __atomic_store_n(&m_Closed,
true, __ATOMIC_RELEASE);
23 for (
auto& binding : m_Bindings)
24 binding->
alive = false;
30void PendingSignalContext::retireThread(
Thread* thread) {
33 for (
auto it = m_Bindings.
begin(); it != m_Bindings.
end();) {
34 if ((*it)->thread == thread) {
36 it = m_Bindings.
erase(it);
46 if (m_Closed || !thread || thread->
getParent() != m_Process || !thread->acceptingEvents())
48 for (
auto& binding : m_Bindings)
49 if (binding->thread == thread && binding->
alive)
52 binding->thread = thread;
59 if (m_Closed || !binding || !binding->alive)
60 return ReadyInvalid | ReadyHangup;
64 !process->
acquireThread(thread, binding->thread) || !thread->acceptingEvents())
65 return ReadyInvalid | ReadyHangup;
67 for (
size_t i = 0; i < 64; ++i)
68 if (mask & (uint64_t(1) << i))
69 generations->read += m_ProcessGenerations[i] + binding->generations[i];
71 return posix_matching_pending(thread.get(), mask) ? ReadyRead : ReadyNone;
73void PendingSignalContext::recordChange(
size_t signal,
Thread* target,
bool processDirected) {
74 if (signal && signal <= 64) {
76 ++m_ProcessGenerations[signal - 1];
78 for (
auto& binding : m_Bindings)
79 if (binding->
alive && binding->thread == target)
80 ++binding->generations[signal - 1];
82 __atomic_add_fetch(&m_Version, uint64_t(1), __ATOMIC_RELEASE);
85void PendingSignalContext::publish() {
88void PendingSignalContext::wake() {
93bool posix_matching_pending(
Thread* caller, uint64_t mask) {
94 if (caller->pendingSignalMask() & mask)
99 if (process->
acquireThread(thread, i - 1) && thread.get() != caller &&
100 (thread->pendingSignalMask(
true) & mask))
106PendingSignalReservation::~PendingSignalReservation() {
109bool PendingSignalReservation::reserve(
Thread* caller, uint64_t mask) {
113 uint64_t available = 0, firstSequence = ~uint64_t(0);
118 const uint64_t candidate = thread->pendingSignalMask(thread.get() != caller) & mask;
119 const uint64_t sequence =
121 ? thread->pendingSignalOrder(__builtin_ctzll(candidate) + 1, thread.get() != caller)
123 if (candidate && (!available || __builtin_ctzll(candidate) < __builtin_ctzll(available) ||
124 (__builtin_ctzll(candidate) == __builtin_ctzll(available) &&
125 sequence < firstSequence))) {
126 available = candidate & (~candidate + 1);
127 firstSequence = sequence;
128 selected = pedigree_std::move(thread);
134 selected->reservePendingSignal(available, selected.get() != caller, firstSequence);
138 m_Selected = pedigree_std::move(selected);
139 m_Delivery = pedigree_std::move(delivery);
144 auto* signal =
static_cast<SignalEvent*
>(m_Delivery.get());
146 result.number = signal->getNumber();
147 result.code = signal->getSignalCode();
148 result.pid = signal->getSenderProcess();
149 result.uid = signal->getSenderUser();
150 result.value = signal->getSignalValue();
151 signal->timerInfo(result.timerId, result.overrun);
152 result.status = signal->childStatus();
153 result.userTime = signal->childUserTime();
154 result.systemTime = signal->childSystemTime();
157void PendingSignalReservation::commit(int32_t overrun) {
160 static_cast<SignalEvent*
>(m_Delivery.get())->completeSignalDelivery(overrun);
163 ->pendingSignalContext()
167void PendingSignalReservation::rollback() {
170 auto* signal =
static_cast<SignalEvent*
>(m_Delivery.get());
171 if (!m_Selected->restorePendingSignal(m_Delivery) && signal->isProcessDirected())
175 ->pendingSignalContext()
181 ByteSet(&info, 0,
sizeof(info));
182 auto put32 = [&](
size_t offset, int32_t value) { MemoryCopy(info.bytes + offset, &value, 4); };
183 auto put64 = [&](
size_t offset, uint64_t value) { MemoryCopy(info.bytes + offset, &value, 8); };
184 put32(0, signal.number);
185 put32(8, signal.code);
186 put32(16, signal.pid);
187 put32(20, signal.uid);
188 put64(24, signal.value);
189 if (signal.code == -2) {
190 put32(16, signal.timerId);
191 put32(20, signal.overrun);
192 }
else if (signal.number == 17 && signal.code > 0 && signal.code <= 6) {
193 put32(24, signal.status);
194 put64(32, signal.userTime);
195 put64(40, signal.systemTime);
MUST_USE_RESULT bool acquireThread(ThreadLease &lease, size_t n)
void notifyReadiness(ReadyMask mask)
void closeReadiness(ReadyMask mask=ReadyInvalid|ReadyHangup)
static Scheduler & instance()
Process * getParent() const
bool sendEvent(Event *pEvent)
Iterator erase(Iterator &Iter)
void pushBack(const T &value)