2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/Scheduler.h"
4#include "pedigree/kernel/process/Thread.h"
5#include "pedigree/kernel/utilities/assert.h"
6#include "pedigree/kernel/utilities/utility.h"
8#include "PosixSubsystem.h"
9#include "trace-context.h"
12size_t localId(
const Thread& thread) {
13 return const_cast<Thread&
>(thread).getId();
22bool TraceTaskToken::live()
const {
23 return snapshot().state == State::Live;
26void TraceTaskToken::publish(
const Thread& thread) {
28 assert(m_Identity.state == State::Staged);
30 m_Identity.localThreadId = localId(thread);
31 m_Identity.linuxTaskId = thread.
getTaskId();
32 m_Identity.state = State::Live;
35void TraceTaskToken::promote(
const Thread& thread) {
37 if (m_Identity.state != State::Live)
40 assert(m_Identity.localThreadId == localId(thread));
41 m_Identity.linuxTaskId = thread.
getTaskId();
44void TraceTaskToken::close() {
46 m_Identity.state = State::Closed;
49PosixTraceContext::~PosixTraceContext() {
52 assert(!m_ThreadCreations && !m_EnrollmentPending);
55bool PosixTraceContext::valid()
const {
56 return !__atomic_load_n(&m_Closed, __ATOMIC_ACQUIRE);
59void PosixTraceContext::attach(
Process& process) {
62 assert(!m_Attached || m_ProcessId == process.
getId());
63 m_ProcessId = process.
getId();
71 if (!m_Attached || !valid())
72 return TraceStatus::Missing;
76 return TraceStatus::NoMemory;
78 if (!prepared.get()->m_Token)
79 return TraceStatus::NoMemory;
80 result = pedigree_std::move(prepared);
81 return TraceStatus::Success;
86 assert(prepared && prepared.get()->m_Token);
88 if (!m_Attached || !valid() || thread.
getParent()->
getId() != m_ProcessId ||
90 return TraceStatus::Missing;
93 if (tokenUnlocked(localId(thread)))
94 return TraceStatus::Denied;
95 prepared.get()->m_Token->publish(thread);
97 node->m_Next = m_Tasks;
99 return TraceStatus::Success;
102TraceTaskRef PosixTraceContext::tokenUnlocked(
size_t id)
const {
103 for (
auto* task = m_Tasks; task; task = task->m_Next) {
104 const auto identity = task->m_Token->snapshot();
105 if (
identity.state == TraceTaskToken::State::Live &&
identity.localThreadId ==
id)
106 return task->m_Token;
111bool PosixTraceContext::ownsTokenUnlocked(
const TraceTaskRef& token)
const {
112 for (
auto* task = m_Tasks; task; task = task->m_Next) {
113 if (task->m_Token == token)
114 return token->live();
124 if (!m_Attached || !valid() || thread.
getParent()->
getId() != m_ProcessId)
126 acquired = tokenUnlocked(localId(thread));
128 result = pedigree_std::move(acquired);
132void PosixTraceContext::setCreator(
const TraceTaskRef& token) {
134 assert(m_Attached && valid() && !m_Tasks && !m_Creator);
143void PosixTraceContext::promoteExec(
const Thread& thread) {
150 token = tokenUnlocked(localId(thread));
152 token->promote(thread);
165bool PosixTraceContext::selectStop(
size_t parentPid,
bool stopped,
bool continued,
bool consume,
168 if (!valid() || !m_Incoming)
170 const auto owner = m_Incoming->tracer()->snapshot();
171 return owner.state == TraceTaskToken::State::Live && owner.processId == parentPid &&
172 m_Incoming->selectStop(stopped, continued, consume, report);
175bool PosixTraceContext::hasIncoming()
const {
177 return bool(m_Incoming);
184 if (m_Incoming.
get() == relation)
185 retired = pedigree_std::move(m_Incoming);
189void PosixTraceContext::retireTask(
const Thread& thread) {
198 auto** position = &m_Tasks;
199 while (*position && (*position)->m_Token->snapshot().localThreadId != localId(thread))
200 position = &(*position)->m_Next;
204 *position = retired->m_Next;
205 retired->m_Token->close();
207 if (m_Incoming && m_Incoming->tracee() == retired->m_Token)
208 incoming = pedigree_std::move(m_Incoming);
211 incoming->taskClosed(retired->m_Token);
213 OwnedRelation* outgoing =
nullptr;
216 auto** position = &m_Outgoing;
217 while (*position && (*position)->relation->tracer() != retired->m_Token)
218 position = &(*position)->next;
220 outgoing = *position;
221 *position = outgoing->next;
226 outgoing->relation->taskClosed(retired->m_Token);
232void PosixTraceContext::close() {
238 OwnedRelation* outgoing =
nullptr;
245 __atomic_store_n(&m_Closed,
true, __ATOMIC_RELEASE);
248 outgoing = m_Outgoing;
249 m_Outgoing =
nullptr;
250 for (
auto* task = tasks; task; task = task->m_Next)
251 task->m_Token->close();
252 creator = pedigree_std::move(m_Creator);
254 incoming = pedigree_std::move(m_Incoming);
257 incoming->taskClosed(incoming->tracee());
259 auto* next = outgoing->next;
260 outgoing->relation->taskClosed(outgoing->relation->tracer());
265 auto* next = tasks->m_Next;
274 return TraceStatus::Missing;
275 const auto identity = token->snapshot();
276 if (
identity.state != TraceTaskToken::State::Live)
277 return TraceStatus::Missing;
280 process->getType() != Process::Posix)
281 return TraceStatus::Missing;
285 return TraceStatus::Missing;
286 auto* subsystem =
static_cast<PosixSubsystem*
>(process->getSubsystem());
288 if (!subsystem || !subsystem->traceContext().taskToken(*task.get(), actual) || actual != token ||
290 return TraceStatus::Missing;
291 result = pedigree_std::move(task);
292 return TraceStatus::Success;
MUST_USE_RESULT bool acquireThreadById(ThreadLease &lease, size_t id)
static Scheduler & instance()
static SharedPointer< TraceTaskToken > tryAllocate(Args...)
@ Continue
No unwind necessary, carry on as normal.
@ TerminateThread
Exit only this thread during Process exit.
UnwindType getUnwindState()
Process * getParent() const
T * releaseOwnership() noexcept