2#include "pedigree/kernel/process/Scheduler.h"
3#include "pedigree/kernel/process/Thread.h"
4#include "pedigree/kernel/process/WaitQueue.h"
5#include "pedigree/kernel/processor/Processor.h"
6#include "pedigree/kernel/processor/ProcessorInformation.h"
7#include "pedigree/kernel/utilities/utility.h"
9#include "PosixProcess.h"
10#include "PosixSubsystem.h"
11#include "trace-context.h"
12#include "trace-state.h"
13#include "wait-state.h"
18 bool active =
false, closed =
false, stopped =
false, report =
false;
19 bool resumed =
false, detached =
false, execTrap =
false;
20 bool ownsReservation =
false;
21 uint64_t generation = 0;
23 bool jobStopped =
false, continueReport =
false;
24 StopKind kind = StopKind::Signal;
25 int signal = 0, replacement = 0;
26 int32_t senderPid = 0;
27 uint32_t senderUid = 0;
35PosixTraceRelation::~PosixTraceRelation() =
default;
36bool PosixTraceRelation::valid()
const {
39bool PosixTraceRelation::activate() {
42 auto guard = m_State.get()->waiters.acquire();
43 if (m_State.get()->closed || m_State.get()->active)
45 m_State.get()->active =
true;
48bool PosixTraceRelation::stopped()
const {
51 auto guard = m_State.get()->waiters.acquire();
52 return m_State.get()->stopped && !m_State.get()->closed && !m_State.get()->resumed;
55 auto guard = m_State.get()->waiters.acquire();
56 if (!m_State.get()->stopped || m_State.get()->closed || m_State.get()->resumed)
57 return TraceStatus::NotStopped;
58 output = m_State.get()->registers;
59 return TraceStatus::Success;
61TraceStatus PosixTraceRelation::snapshotSignalInfo(
TraceSignalInfo& output)
const {
62 auto guard = m_State.get()->waiters.acquire();
63 if (!m_State.get()->stopped || m_State.get()->closed || m_State.get()->resumed)
64 return TraceStatus::NotStopped;
65 if (m_State.get()->kind == StopKind::Group)
66 return TraceStatus::Invalid;
67 output = m_State.get()->info;
68 return TraceStatus::Success;
70bool PosixTraceRelation::selectStop(
bool stopped,
bool continued,
bool consume,
72 auto guard = m_State.get()->waiters.acquire();
73 if (m_State.get()->closed)
75 if (stopped && m_State.get()->stopped && m_State.get()->report) {
76 output = m_State.get()->waitReport;
78 m_State.get()->report =
false;
81 if (continued && m_State.get()->continueReport) {
82 output = m_State.get()->continuationReport;
84 m_State.get()->continueReport =
false;
89TraceStatus PosixTraceRelation::resume(
int signal,
bool detach) {
90 if (signal < 0 || signal > 64)
91 return TraceStatus::Invalid;
93 bool prepare =
false, inheritReservation =
false;
95 auto guard = m_State.get()->waiters.acquire();
96 if (!m_State.get()->stopped || m_State.get()->closed || m_State.get()->resumed)
97 return TraceStatus::NotStopped;
98 generation = m_State.get()->generation;
99 prepare = signal && m_State.get()->kind != StopKind::Group &&
100 (m_State.get()->kind == StopKind::Exec || signal != m_State.get()->signal);
101 inheritReservation = m_State.get()->ownsReservation;
105 const auto credentials = caller->snapshotCredentials();
108 const auto status = posix_trace_prepare_resume(m_Tracee, signal, inheritReservation,
109 static_cast<int32_t
>(caller->getUserspaceId()),
110 credentials.ruid, prepared);
111 if (status != TraceStatus::Success)
115 auto guard = m_State.get()->waiters.acquire();
116 if (!m_State.get()->stopped || m_State.get()->closed || m_State.get()->resumed ||
117 m_State.get()->generation != generation)
118 return TraceStatus::NotStopped;
119 m_State.get()->prepared = pedigree_std::move(prepared);
120 m_State.get()->senderPid =
static_cast<int32_t
>(caller->getUserspaceId());
121 m_State.get()->senderUid = credentials.ruid;
122 m_State.get()->replacement = signal;
123 m_State.get()->detached = detach;
124 if (m_State.get()->kind == StopKind::Group && !detach)
125 m_State.get()->jobStopped =
false;
126 m_State.get()->resumed =
true;
127 m_State.get()->report =
false;
132 return TraceStatus::Success;
134void PosixTraceRelation::taskClosed(
const TraceTaskRef& task) {
135 if (!valid() || (task != m_Tracer && task != m_Tracee))
139 auto guard = m_State.get()->waiters.acquire();
140 if (m_State.get()->closed)
142 m_State.get()->closed =
true;
143 m_State.get()->active =
false;
144 m_State.get()->detached =
true;
145 if (!m_State.get()->resumed)
146 m_State.get()->replacement =
147 task == m_Tracer && m_State.get()->kind != StopKind::Exec ? m_State.get()->signal : 0;
148 m_State.get()->resumed =
true;
149 if (task == m_Tracee)
150 retired = pedigree_std::move(m_State.get()->prepared);
151 m_State.get()->report =
false;
156void PosixTraceRelation::unlink() {
161 if (posix_trace_acquire_task(m_Tracee, task) == TraceStatus::Success) {
163 subsystem->traceContext().clearIncoming(
this);
164 task->clearSignalFrameRequirement();
168 if (posix_trace_acquire_task(m_Tracer, tracer) == TraceStatus::Success) {
170 subsystem->traceContext().unregisterTracee(
this);
173void PosixTraceRelation::continued(
Process& process) {
176 auto guard = m_State.get()->waiters.acquire();
182 report.uid =
static_cast<PosixProcess&
>(process).snapshotCredentials().ruid;
183 report.cause = PosixWait::Continue;
185 report.userNanoseconds = process.
getUserTime() + process.getReapedChildrenUserTime();
186 report.kernelNanoseconds = process.getKernelTime() + process.getReapedChildrenKernelTime();
188 auto guard = m_State.get()->waiters.acquire();
189 if (m_State.get()->jobStopped && !m_State.get()->closed) {
190 m_State.get()->continuationReport = report;
191 m_State.get()->continueReport =
true;
192 m_State.get()->jobStopped =
false;
193 parentGuard.wakeAll();
197void PosixTraceRelation::imageCommitted() {
198 auto guard = m_State.get()->waiters.acquire();
199 if (!m_State.get()->closed && m_State.get()->active) {
200 m_State.get()->execTrap =
true;
201 m_State.get()->report =
false;
202 m_State.get()->stopped =
false;
205bool PosixTraceRelation::takeExecTrap() {
206 auto guard = m_State.get()->waiters.acquire();
207 const bool pending = m_State.get()->execTrap && !m_State.get()->closed;
208 m_State.get()->execTrap =
false;
212 StopKind kind,
int signal,
214 bool ownsReservation) {
216 if (!frame.snapshot(copy) || copy.architecture != UserRegisterSnapshot::Architecture::Amd64)
217 return {0,
false,
true};
221 report.uid =
static_cast<PosixProcess*
>(process)->snapshotCredentials().ruid;
223 report.status = signal;
224 report.userNanoseconds = process->
getUserTime() + process->getReapedChildrenUserTime();
225 report.kernelNanoseconds = process->getKernelTime() + process->getReapedChildrenKernelTime();
226 thread.setUserReturnSignalParked(
true);
230 thread.setUserReturnSignalParked(
false);
234 [](
void* value) {
static_cast<Thread*
>(value)->setUserReturnSignalParked(
false); }, &thread);
238 return {kind == StopKind::Exec ? 0 : signal,
true,
false};
241 return {0,
false,
false};
242 auto guard = m_State.get()->waiters.acquire();
243 if (m_State.get()->closed || !m_State.get()->active)
244 return {kind == StopKind::Exec ? 0 : signal,
true,
false};
245 ++m_State.get()->generation;
246 m_State.get()->ownsReservation = ownsReservation;
247 m_State.get()->kind = kind;
248 if (kind == StopKind::Group)
249 m_State.get()->jobStopped =
true;
250 m_State.get()->signal = signal;
251 m_State.get()->registers = copy.amd64;
252 m_State.get()->info = info;
253 m_State.get()->waitReport = report;
254 m_State.get()->stopped =
true;
255 m_State.get()->report =
true;
256 m_State.get()->resumed =
false;
257 parentGuard.wakeAll();
264 auto* subsystem =
static_cast<PosixSubsystem*
>(parent->getSubsystem());
266 if (subsystem && subsystem->getSignalDisposition(17, disposition) &&
267 !(disposition.flags & 1U ))
268 subsystem->queueSignalDelivery(recipient.get(), 17,
nullptr, 4,
true, signal);
273 auto guard = m_State.get()->waiters.acquire();
275 result.terminal =
true;
278 if (m_State.get()->resumed) {
279 result.signal = m_State.get()->replacement;
280 result.detached = m_State.get()->detached;
281 result.pid = m_State.get()->senderPid;
282 result.uid = m_State.get()->senderUid;
283 result.prepared = pedigree_std::move(m_State.get()->prepared);
287 if (wake == WaitQueue::WakeReason::Terminating || wake == WaitQueue::WakeReason::Unwinding) {
288 result.terminal =
true;
293 auto guard = m_State.get()->waiters.acquire();
294 m_State.get()->stopped =
false;
295 m_State.get()->report =
false;
297 thread.setUserReturnSignalParked(
false);
298 if (kind == StopKind::Group && result.detached && !result.terminal)
size_t getUserspaceId() const
MUST_USE_RESULT bool acquireProcessSignalThread(ThreadLease &lease)
WaitQueue::Guard acquireChildStateWait()
void suspendIfContinuationEpoch(int stopSignal, size_t continuationEpoch)
Time::Timestamp getUserTime() const
size_t getContinuationEpoch()
static ProcessorInformation & information()
static Scheduler & instance()
MUST_USE_RESULT bool acquireProcess(ProcessLease &lease, size_t n)
@ Continue
No unwind necessary, carry on as normal.
UnwindType getUnwindState()
Process * getParent() const