The Pedigree Project 0.1
AdmittedThread.cc
1/*
2 * Copyright (c) 2026, Pedigree Developers
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted.
6 */
7
8#include "pedigree/kernel/Log.h"
9#include "pedigree/kernel/panic.h"
10#include "pedigree/kernel/process/AdmittedThread.h"
11#include "pedigree/kernel/process/OperationBarrier.h"
12#include "pedigree/kernel/process/Scheduler.h"
13#include "pedigree/kernel/process/Thread.h"
14#include "pedigree/kernel/utilities/String.h"
15#include "pedigree/kernel/utilities/utility.h"
16
17#if (HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS) || PEDIGREE_CONCURRENCY_SMOKE_TESTS
18namespace {
19AdmittedThread::BeforeStartHook g_BeforeStartHook = nullptr;
20void* g_BeforeStartHookContext = nullptr;
21} // namespace
22#endif
23
25 Context(Entry entry, void* parameter, Cancel cancel, OperationBarrier::Lease&& admission)
26 : entry(entry),
27 parameter(parameter),
28 cancel(cancel),
29 admission(pedigree_std::move(admission)) {}
30
31 Entry entry;
32 void* parameter;
33 Cancel cancel;
35};
36
37bool AdmittedThread::launchDetached(Entry entry, void* parameter, Cancel cancel,
38 OperationBarrier& barrier, const char* name) {
39 if (!entry) {
40 return false;
41 }
42
44 if (!barrier.tryAcquire(admission)) {
45 return false;
46 }
47
48 Context* context = new Context(entry, parameter, cancel, pedigree_std::move(admission));
49 if (!context) {
50 return false;
51 }
52
53 Process* kernelProcess = Scheduler::instance().getKernelProcess();
54 Thread* thread =
55 new Thread(kernelProcess, trampoline, context, nullptr, false, true, true, cancelBeforeStart);
56 if (!thread) {
57 delete context;
58 return false;
59 }
60
61 if (name) {
62 thread->setName(String(name));
63 }
64
65#if (HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS) || PEDIGREE_CONCURRENCY_SMOKE_TESTS
66 if (g_BeforeStartHook) {
67 g_BeforeStartHook(thread, g_BeforeStartHookContext);
68 }
69#endif
70 if (!thread->startDetached()) {
71 panic("AdmittedThread could not publish its detached worker.");
72 }
73
74 return true;
75}
76
77#if (HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS) || PEDIGREE_CONCURRENCY_SMOKE_TESTS
78void AdmittedThread::setBeforeStartHookForTest(BeforeStartHook hook, void* context) {
79 g_BeforeStartHook = hook;
80 g_BeforeStartHookContext = context;
81}
82#endif
83
84void AdmittedThread::cancelBeforeStart(void* parameter) {
85 Context* context = reinterpret_cast<Context*>(parameter);
86 if (context->cancel) {
87 context->cancel(context->parameter);
88 }
89 delete context;
90}
91
92int AdmittedThread::trampoline(void* parameter) {
93 Context* context = reinterpret_cast<Context*>(parameter);
94 const Entry entry = context->entry;
95 void* entryParameter = context->parameter;
96
97 const int result = entry(entryParameter);
98
99 // This destructor releases admission in kernel text. Once a close waiter
100 // wakes, no return address or live frame still points into the entry module.
101 delete context;
102 return result;
103}
static MUST_USE_RESULT bool launchDetached(Entry entry, void *parameter, Cancel cancel, OperationBarrier &barrier, const char *name=nullptr)
MUST_USE_RESULT bool tryAcquire(Lease &lease)
static Scheduler & instance()
Definition Scheduler.h:96
bool startDetached()
Definition Thread.cc:812
void EXPORTED_PUBLIC panic(const char *msg) NORETURN
Definition panic.cc:117