24#include "pedigree/kernel/ActivityDiagnostics.h"
25#if PEDIGREE_LATENCY_ACCOUNTING
26#include "pedigree/kernel/LatencyAccounting.h"
28#include "pedigree/kernel/LockGuard.h"
29#include "pedigree/kernel/Log.h"
30#include "pedigree/kernel/Metrics.h"
31#include "pedigree/kernel/Subsystem.h"
32#include "pedigree/kernel/process/Mutex.h"
33#include "pedigree/kernel/process/PerProcessorScheduler.h"
34#include "pedigree/kernel/process/Process.h"
35#include "pedigree/kernel/process/ProcessorThreadAllocator.h"
36#include "pedigree/kernel/process/Scheduler.h"
37#include "pedigree/kernel/process/SignalEvent.h"
38#include "pedigree/kernel/process/TerminationDeferral.h"
39#include "pedigree/kernel/process/Thread.h"
40#include "pedigree/kernel/process/Uninterruptible.h"
41#include "pedigree/kernel/process/eventNumbers.h"
42#include "pedigree/kernel/processor/NMFaultHandler.h"
43#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
44#include "pedigree/kernel/processor/Processor.h"
45#include "pedigree/kernel/processor/ProcessorInformation.h"
46#include "pedigree/kernel/processor/state.h"
47#include "pedigree/kernel/utilities/ExtensibleBitmap.h"
48#include "pedigree/kernel/utilities/Iterator.h"
49#include "pedigree/kernel/utilities/MemoryAllocator.h"
50#include "pedigree/kernel/utilities/Vector.h"
51#include "pedigree/kernel/utilities/utility.h"
55 return m_SecurityState;
58void Thread::setSecurityState(
const SecurityStateRef& state) {
59 SecurityStateRef previous;
62 previous = pedigree_std::move(m_SecurityState);
63 m_SecurityState =
state;
64 __atomic_store_n(&m_HasSecurityState,
bool(
state), __ATOMIC_RELEASE);
68Thread::StackDiscardScope::StackDiscardScope(DeferredScopeRecord::Cleanup cleanup,
void* context)
69 : m_pThread(cleanup ?
Processor::information().getCurrentThread() : nullptr), m_Record() {
70 if (cleanup && !m_pThread) {
71 FATAL(
"StackDiscardScope cleanup has no current Thread.");
74 m_pThread->armStateCleanup(m_Record, cleanup, context);
78Thread::StackDiscardScope::~StackDiscardScope() {
82void Thread::StackDiscardScope::disarm() {
84 m_pThread->disarmStateCleanup(m_Record);
89Thread::TemporarySignalMask::TemporarySignalMask(
Thread& thread, uint64_t signalMask)
90 : m_pThread(&thread), m_StateLevel(0), m_Record() {
93 m_StateLevel = thread.beginTemporarySignalMask(signalMask);
94 thread.armStateCleanup(m_Record, &TemporarySignalMask::discard,
this);
98Thread::TemporarySignalMask::~TemporarySignalMask() {
106 FATAL(
"Temporary signal mask restored more than once.");
111 const bool interrupted = m_pThread->finishTemporarySignalMask(m_StateLevel);
112 m_pThread->disarmStateCleanup(m_Record);
118void Thread::TemporarySignalMask::discard(
void* context) {
120 if (!scope || !scope->m_pThread) {
121 FATAL(
"Invalid temporary signal mask discard.");
126 scope->m_pThread->finishTemporarySignalMask(scope->m_StateLevel,
false);
127 scope->m_pThread =
nullptr;
131#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
133Thread::StateTransitionHook g_StateTransitionHook =
nullptr;
134Thread::JoinOperationHook g_JoinOperationHook =
nullptr;
135Thread::ExternalLeaseReleaseHook g_ExternalLeaseReleaseHook =
nullptr;
136Thread* g_ExternalLeaseReleaseTarget =
nullptr;
137Thread::SignalWaitPreEnrolmentHook g_SignalWaitPreEnrolmentHook =
nullptr;
138Thread* g_SignalWaitPreEnrolmentTarget =
nullptr;
139Thread::TlsResetHook g_TlsResetHook =
nullptr;
140Thread* g_TlsResetTarget =
nullptr;
141using EventAdmissionHook = void (*)(
Thread*);
142EventAdmissionHook g_EventAdmissionHook =
nullptr;
143Thread* g_EventAdmissionTarget =
nullptr;
145struct HostedStateCleanupOrder {
146 size_t values[8] = {};
150struct HostedStateCleanupItem {
151 HostedStateCleanupOrder* order;
155void hostedStateCleanupCallback(
void* context) {
156 HostedStateCleanupItem* item =
reinterpret_cast<HostedStateCleanupItem*
>(context);
157 if (item && item->order && item->order->count < 8) {
158 item->order->values[item->order->count++] = item->value;
162void observeStateTransition(Thread::StateTransitionWindow window,
Thread* thread,
163 size_t previousLevel,
size_t nextLevel) {
164 Thread::StateTransitionHook hook = __atomic_load_n(&g_StateTransitionHook, __ATOMIC_ACQUIRE);
166 hook(window, thread, previousLevel, nextLevel);
177constexpr size_t HostedPreallocatedUserStateLevel = 2;
178static_assert(MAX_NESTED_EVENTS > HostedPreallocatedUserStateLevel,
179 "Hosted return-tail state levels exceed the Thread nesting limit");
182void requireThreadDestructionContext() {
185 FATAL_NOLOCK(
"Thread destruction requires an IRQ-enabled WaitableThread boundary.");
191 explicit CpuTimeSample(
bool interruptsAlreadyDisabled =
false)
194 m_InterruptsWereEnabled(false),
195 m_RestoreInterrupts(!interruptsAlreadyDisabled) {
196 if (!interruptsAlreadyDisabled) {
203 const auto sample = Time::sampleCpuTime();
204 processor = sample.processor;
205 timestamp = sample.timestamp;
209 if (m_RestoreInterrupts) {
214 Time::Timestamp timestamp;
218 bool m_InterruptsWereEnabled;
219 bool m_RestoreInterrupts;
225 bool semiUser,
bool bDontPickCore,
bool delayedStart,
229 FATAL(
"Thread::Thread(): Parent process was NULL!");
231 initialisePlacement(placement);
241 if (pCurrent && pCurrent->
getParent() == pParent) {
246 bool bUserMode =
true;
247 void* requestedStack = pStack;
255 pStack = kernelStack->getTop();
265 if (!requestedStack) {
271 if (requestedStack || semiUser) {
275 for (
size_t level = 1; level <= HostedPreallocatedUserStateLevel; ++level) {
283 *
this, pCurrent && pCurrent->
getParent() == pParent ? pCurrent :
nullptr);
295 if (!bDontPickCore || placement) {
296 ProcessorThreadAllocator::instance().
addThread(
this, pStartFunction, pParam, bUserMode, pStack);
305 : m_pParent(pParent),
306 m_DeferredReapNode(this),
307 m_pScheduler(&
Processor::information().getScheduler()) {
309 FATAL(
"Thread::Thread(): Parent process was NULL!");
311 m_pParent->inheritFilesystemIds(*
this,
nullptr);
324 : m_pParent(pParent), m_DeferredReapNode(this) {
326 FATAL(
"Thread::Thread(): Parent process was NULL!");
328 initialisePlacement(placement);
338 for (
size_t level = 1; level <= HostedPreallocatedUserStateLevel; ++level) {
359 m_pParent->inheritFilesystemIds(*
this, pCurrent);
371 m_UserGsBase =
state.getUserEntryMetadata().gsBase;
385 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
386 const CpuTimeSample sample;
393 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
394 const CpuTimeSample sample;
395 const Time::Timestamp elapsed =
406 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
407 const CpuTimeSample sample(interruptsAlreadyDisabled);
408 const Time::Timestamp elapsed =
417 (void)interruptsAlreadyDisabled;
423 if constexpr (PEDIGREE_TIME_ACCOUNTING && PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
436 Time::Timestamp* total = mode == CpuTimeMode::User ? &
m_UserTime : &m_KernelTime;
440 asm volatile(
"addq %1, %0" :
"+m"(*total) :
"r"(elapsed) :
"cc");
442 __atomic_fetch_add(total, elapsed, __ATOMIC_RELAXED);
444#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
445 if (mode == CpuTimeMode::Kernel) {
446 const size_t slot = __atomic_load_n(&m_ActiveSyscallTimingSlot, __ATOMIC_ACQUIRE);
447 if (slot != NoSyscallTimingSlot) {
448 m_pParent->recordSyscallTimingKernel(slot, elapsed);
452#if PEDIGREE_LATENCY_ACCOUNTING
454 LatencyAccounting::recordDeferredCpu(elapsed);
457 m_pParent->reportTimeAccounting(elapsed);
461#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
462void Thread::publishTimeAccountingForHostedTest(Time::Timestamp user, Time::Timestamp system) {
481 "Thread destroyed before external leases were closed and "
486 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
488 FATAL(
"Thread destroyed with armed state cleanup records.");
491 for (
size_t service = 0; service < serviceEnd; ++service) {
493 FATAL(
"Thread destroyed with an admitted syscall.");
498 FATAL(
"Thread destroyed with active deferral scopes: terminal="
509 for (
size_t i = 0; i < MAX_NESTED_EVENTS; i++) {
517 physical_uintptr_t phys = 0;
525 uintptr_t base =
reinterpret_cast<uintptr_t
>(
m_pTlsBase);
527 m_pParent->freeUserRange(Process::UserRegion::Dynamic, base, THREAD_TLS_SIZE);
529 m_pParent->freeUserRange(Process::UserRegion::Normal, base, THREAD_TLS_SIZE);
531 ERROR(
"Thread: no parent, but a TLS base exists.");
544 Metrics::increment(Metrics::ThreadDestroyed);
558 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
560 if (!stack || !stack->regionId() || !
m_pParent)
562 for (
size_t other = level; other < MAX_NESTED_EVENTS; ++other) {
563 if (m_StateLevels[other].m_pUserStack == stack)
564 m_StateLevels[other].m_pUserStack =
nullptr;
578 Metrics::increment(Metrics::ThreadExitStarted);
593 const WaitQueue::WakeReason reason = senderGuard.waitForCompletion(
608 Event*
event =
nullptr;
644 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
648 queue->cancel(&
waiter, WaitQueue::WakeReason::Terminating);
664void Thread::setRobustList(uintptr_t address,
size_t ownerId) {
667 m_RobustListOwnerId = ownerId;
668 __atomic_store_n(&
m_RobustList, address, __ATOMIC_RELEASE);
672uintptr_t Thread::takeRobustList(
size_t& ownerId) {
674 ownerId = m_RobustListOwnerId;
675 m_RobustListOwnerId = 0;
676 return __atomic_exchange_n(&
m_RobustList, uintptr_t(0), __ATOMIC_ACQ_REL);
679void Thread::forceToStartupProcessor() {
687 "Thread::forceToStartupProcessor must be run as the desired "
697 migratable = m_Placement.migratable;
698 m_Placement.migratable =
true;
701 startup.set(destination->logicalCpu());
703 uint64_t generation = 0;
705 if (result != AffinityResult::Success && result != AffinityResult::Busy)
706 FATAL(
"Cannot admit startup processor migration.");
707 if (
waitAffinity(generation) != AffinityResult::Success)
708 FATAL(
"Startup processor migration was terminated.");
709 if (result == AffinityResult::Success)
713 FATAL(
"Startup processor migration was terminated at its safe point.");
716 m_Placement.migratable = migratable;
721 setStatusUnlocked(s);
726 if (s != Thread::Zombie) {
727 WARNING(
"Error condition in Thread::setStatus, more info below...");
730 "Thread::setStatus called with non-zombie status, when the "
731 "thread is a zombie!");
737 if (s == Thread::Zombie) {
740 FATAL(
"Thread zombie transition must use off-stack retirement.");
775 bool claimed =
false;
776 bool processExitOwned =
false;
793 if (processExitOwned) {
796 const bool started =
start();
802 bool deleteNow =
false;
823 requireThreadDestructionContext();
837 const size_t level = __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE);
842 const size_t previousLevel = __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE);
843 if ((previousLevel + 1) >= MAX_NESTED_EVENTS) {
844 ERROR(
"Thread: Max nested events!");
847 const size_t nextLevel = previousLevel + 1;
850 if (m_StateLevels[0].m_pKernelStack && nextLevel <= HostedPreallocatedUserStateLevel &&
851 !m_StateLevels[nextLevel].m_pKernelStack) {
852 FATAL_NOLOCK(
"Hosted user Thread reached an unallocated return state stack");
857 FATAL(
"Thread state level reused with an armed cleanup record.");
868 m_StateLevels[nextLevel].
m_State->flags &= ~(1U << 1);
870 m_StateLevels[nextLevel].m_InterruptionReason = NotInterrupted;
873 m_StateLevels[nextLevel].m_TemporarySignalMaskActive =
false;
874 m_StateLevels[nextLevel].m_TemporarySignalWaitInterrupted =
false;
875 m_StateLevels[nextLevel].m_DeferredSignalMaskRestore =
false;
877 m_StateLevels[nextLevel].m_DispatchedSignalContinuationEpoch = 0;
883#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
884 observeStateTransition(StatePushBeforePublish,
this, previousLevel, nextLevel);
887 SchedulerState* previousState = m_StateLevels[previousLevel].
m_State;
893 FATAL(
"Thread state level changed during push publication.");
899 m_StateLevels[nextLevel].
m_Errno = m_StateLevels[previousLevel].
m_Errno;
900 __atomic_store_n(&
m_nStateLevel, nextLevel, __ATOMIC_RELEASE);
903#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
904 observeStateTransition(StatePushAfterPublish,
this, previousLevel, nextLevel);
910 return previousState;
917 const size_t origStateLevel = __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE);
919 if (origStateLevel == 0) {
920 ERROR(
"Thread: Potential error: popStack() called with state level 0!");
921 ERROR(
"Thread: (ignore this if longjmp has been called)");
927 FATAL(
"Normal state pop attempted with armed cleanup records.");
930 const size_t nextLevel = origStateLevel - 1;
934 FATAL(
"Thread state level changed during pop publication.");
936 if (m_StateLevels[origStateLevel].m_bOwnsAlternateSignalStack) {
940 __atomic_store_n(&
m_nStateLevel, nextLevel, __ATOMIC_RELEASE);
943#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
944 observeStateTransition(StatePopAfterPublish,
this, origStateLevel, nextLevel);
957 const size_t level = __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE);
959 FATAL(
"Cannot abandon the base Thread state.");
961 retireDeferredScopes(
false, level);
983 FATAL(
"Exec attempted to discard another Thread's user stacks.");
987 size_t discardedCount = 0;
990 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
992 m_StateLevels[level].m_pUserStack =
nullptr;
997 bool alreadyDiscarded =
false;
998 for (
size_t i = 0; i < discardedCount; ++i) {
999 if (discarded[i] == stack) {
1000 alreadyDiscarded =
true;
1004 if (!alreadyDiscarded) {
1005 discarded[discardedCount++] = stack;
1013 for (
size_t i = 0; i < discardedCount; ++i) {
1014 delete discarded[i];
1020 FATAL(
"Cannot adopt an empty exec user stack.");
1024 if (m_StateLevels[0].m_pUserStack) {
1025 FATAL(
"Exec attempted to replace an owned base user stack.");
1027 m_StateLevels[0].m_pUserStack = stack;
1033 FATAL(
"Kernel thread root returned without a current Thread.");
1036 FATAL(
"Kernel thread root returned with nested event state still active.");
1040 if (unwindState ==
Exit) {
1042 Subsystem* subsystem = process ? process->getSubsystem() :
nullptr;
1044 FATAL(
"Kernel thread root reached process exit without a subsystem.");
1047 subsystem->
exit(request.code, request.cause);
1048 FATAL(
"Subsystem::exit returned to a kernel thread root.");
1055 if (stateLevel >= MAX_NESTED_EVENTS)
1056 stateLevel = MAX_NESTED_EVENTS - 1;
1057 if (m_StateLevels[stateLevel].m_pKernelStack == 0)
1063 SchedulerState*
state = m_StateLevels[stateLevel].
m_State;
1064 state->stackBase =
reinterpret_cast<uintptr_t
>(stack->getBase());
1065 state->stackSize = stack->getSize();
1072 FATAL(
"m_nStateLevel > MAX_NESTED_EVENTS: " <<
m_nStateLevel <<
"...");
1082 FATAL(
"m_nStateLevel > MAX_NESTED_EVENTS: " <<
m_nStateLevel <<
"...");
1090 *size = stack->getSize();
1091 return stack->getBase();
1093 ERROR(
"No kernel stack at this level!");
1100 uintptr_t stack = 0;
1108 if (stateLevel >= MAX_NESTED_EVENTS) {
1109 ERROR(
"Thread::pokeState(): stateLevel `" << stateLevel <<
"' is over the maximum.");
1117 if (!eventSendLease) {
1121 bool accepted =
false;
1133#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1134 EventAdmissionHook admissionHook = __atomic_load_n(&g_EventAdmissionHook, __ATOMIC_ACQUIRE);
1135 Thread* admissionTarget = __atomic_load_n(&g_EventAdmissionTarget, __ATOMIC_ACQUIRE);
1136 if (admissionHook && admissionTarget ==
this) {
1137 admissionHook(
this);
1145 bool duplicate =
false;
1146 bool wakeThread =
false;
1148 if (eventRegistered) {
1156 if ((*it)->isSignalEvent() && (*it)->getNumber() == pEvent->
getNumber() &&
1157 static_cast<SignalEvent*
>(*it)->isProcessDirected() ==
1158 static_cast<SignalEvent*
>(pEvent)->isProcessDirected()) {
1167 markUserReturnWorkPending();
1168 wakeThread = hasDeliverableEventsUnlocked() &&
1176 if (!eventRegistered) {
1178 }
else if (!accepted) {
1180 }
else if (duplicate) {
1182 }
else if (wakeThread) {
1183 assert(readyScheduler);
1189 bool drained =
false;
1203 void* stackDiscardContext) {
1204 waitForEventInternal(
false, onStackDiscard, stackDiscardContext);
1208 void* stackDiscardContext) {
1209 return waitForEventInternal(
true, onStackDiscard, stackDiscardContext);
1212bool Thread::waitForEventInternal(
bool stopOnSignalInterruption,
1213 WaitQueue::StackDiscardCleanup onStackDiscard,
1214 void* stackDiscardContext) {
1215 StackDiscardScope discardScope(onStackDiscard, stackDiscardContext);
1222 bool signalInterrupted =
false;
1223 WaitQueue::WakeReason reason = WaitQueue::WakeReason::Spurious;
1224#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1225 if (stopOnSignalInterruption) {
1226 SignalWaitPreEnrolmentHook hook =
1227 __atomic_load_n(&g_SignalWaitPreEnrolmentHook, __ATOMIC_ACQUIRE);
1228 Thread* hookTarget = __atomic_load_n(&g_SignalWaitPreEnrolmentTarget, __ATOMIC_ACQUIRE);
1229 if (hook && hookTarget ==
this) {
1238 ready = hasDeliverableEventsUnlocked();
1239 if (stopOnSignalInterruption) {
1241 signalInterrupted =
state.m_TemporarySignalMaskActive &&
1242 state.m_TemporarySignalWaitInterrupted &&
1243 state.m_InterruptionReason == InterruptedBySignal;
1246 if (!ready && !signalInterrupted) {
1248 reinterpret_cast<uintptr_t
>(__builtin_return_address(0)));
1252 if (signalInterrupted) {
1267 if (reason == WaitQueue::WakeReason::Event || reason == WaitQueue::WakeReason::Terminating ||
1268 reason == WaitQueue::WakeReason::Unwinding) {
1274#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1283Event* g_pHostedSelfRetireEvent =
nullptr;
1285struct HostedAdmissionRetireContext {
1286 HostedAdmissionRetireContext(
Event* event,
size_t destructionsBefore)
1287 : event(event), destructionsBefore(destructionsBefore), calls(0), destroyedInsideHook(0) {}
1290 size_t destructionsBefore;
1295HostedAdmissionRetireContext* g_pHostedAdmissionRetireContext =
nullptr;
1297void hostedPrequeuedEventHandler(
size_t) {
1298 g_HostedPrequeuedEventCalls += 1;
1301void hostedShutdownEventHandler(
size_t) {
1302 g_HostedShutdownEventCalls += 1;
1305void hostedSelfRetireEventHandler(
size_t) {
1306 Event*
event = g_pHostedSelfRetireEvent;
1307 g_pHostedSelfRetireEvent =
nullptr;
1310 g_HostedSelfRetireCalls += 1;
1314void hostedAdmissionRetireHook(
Thread*) {
1315 HostedAdmissionRetireContext* context = g_pHostedAdmissionRetireContext;
1320 context->calls += 1;
1321 context->event->retire();
1322 if (g_HostedAdmissionRetireDestructions != context->destructionsBefore) {
1323 context->destroyedInsideHook += 1;
1327class HostedPrequeuedEvent :
public Event {
1329 HostedPrequeuedEvent()
1330 :
Event(reinterpret_cast<uintptr_t>(&hostedPrequeuedEventHandler), false) {}
1341class HostedShutdownStableEvent :
public Event {
1343 HostedShutdownStableEvent()
1344 :
Event(reinterpret_cast<uintptr_t>(&hostedShutdownEventHandler), false) {}
1355class HostedShutdownDeletableEvent :
public Event {
1357 HostedShutdownDeletableEvent()
1358 :
Event(reinterpret_cast<uintptr_t>(&hostedShutdownEventHandler), true) {}
1360 ~HostedShutdownDeletableEvent()
override {
1361 g_HostedShutdownEventDestructions += 1;
1373class HostedSelfRetireEvent :
public Event {
1375 HostedSelfRetireEvent()
1376 :
Event(reinterpret_cast<uintptr_t>(&hostedSelfRetireEventHandler), false) {}
1378 ~HostedSelfRetireEvent()
override {
1379 g_HostedSelfRetireDestructions += 1;
1391class HostedAdmissionRetireEvent :
public Event {
1393 HostedAdmissionRetireEvent()
1394 :
Event(reinterpret_cast<uintptr_t>(&hostedShutdownEventHandler), false) {}
1396 ~HostedAdmissionRetireEvent()
override {
1397 g_HostedAdmissionRetireDestructions += 1;
1409int hostedShutdownThread(
void*) {
1410 g_HostedShutdownThreadCalls += 1;
1414struct HostedStatePublicationContext {
1415 HostedStatePublicationContext(
Thread* thread,
Event* event)
1416 : thread(thread), event(event), calls(0), failures(0) {}
1424HostedStatePublicationContext* g_StatePublicationContext =
nullptr;
1426void hostedStatePublicationHook(Thread::StateTransitionWindow window,
Thread* thread,
1427 size_t previousLevel,
size_t nextLevel) {
1428 HostedStatePublicationContext* context =
1429 __atomic_load_n(&g_StatePublicationContext, __ATOMIC_ACQUIRE);
1434 context->calls += 1;
1435 const size_t expectedVisibleLevel =
1436 window == Thread::StatePushBeforePublish ? previousLevel : nextLevel;
1437 if (thread != context->thread || thread->
getStateLevel() != expectedVisibleLevel ||
1440 context->failures += 1;
1444struct HostedDeliveryLeaseContext {
1445 explicit HostedDeliveryLeaseContext(
Event* event) : event(event), entered(0), completed(0) {}
1452int hostedDeliveryLeaseWaiter(
void* parameter) {
1453 HostedDeliveryLeaseContext* context =
reinterpret_cast<HostedDeliveryLeaseContext*
>(parameter);
1454 context->entered += 1;
1455 context->event->waitForDeliveries();
1456 context->completed += 1;
1461void Thread::setStateTransitionHook(StateTransitionHook hook) {
1462 __atomic_store_n(&g_StateTransitionHook, hook, __ATOMIC_RELEASE);
1465void Thread::setJoinOperationHook(JoinOperationHook hook) {
1466 __atomic_store_n(&g_JoinOperationHook, hook, __ATOMIC_RELEASE);
1469void Thread::setExternalLeaseReleaseHookForHostedTest(
Thread* target,
1470 ExternalLeaseReleaseHook hook) {
1471 __atomic_store_n(&g_ExternalLeaseReleaseTarget, target, __ATOMIC_RELEASE);
1472 __atomic_store_n(&g_ExternalLeaseReleaseHook, hook, __ATOMIC_RELEASE);
1475void Thread::setSignalWaitPreEnrolmentHookForHostedTest(
Thread* target,
1476 SignalWaitPreEnrolmentHook hook) {
1477 __atomic_store_n(&g_SignalWaitPreEnrolmentTarget, target, __ATOMIC_RELEASE);
1478 __atomic_store_n(&g_SignalWaitPreEnrolmentHook, hook, __ATOMIC_RELEASE);
1481void Thread::setTlsResetHookForHostedTest(
Thread* target, TlsResetHook hook) {
1482 __atomic_store_n(&g_TlsResetTarget, target, __ATOMIC_RELEASE);
1483 __atomic_store_n(&g_TlsResetHook, hook, __ATOMIC_RELEASE);
1486bool Thread::isReapableForHostedTest() {
1491bool Thread::wasStartPublishedForHostedTest() {
1496bool Thread::waitUntilReapableForHostedTest() {
1510bool Thread::runHostedPrequeuedEventRegression() {
1515 constexpr size_t Iterations = 16;
1516 HostedPrequeuedEvent event;
1518 const size_t callsBefore = g_HostedPrequeuedEventCalls;
1519 for (
size_t iteration = 0; iteration < Iterations; ++iteration) {
1526 if (g_HostedPrequeuedEventCalls != (callsBefore + iteration + 1) || event.pendingCount() != 0 ||
1535bool Thread::runHostedStatePublicationRegression() {
1541 HostedPrequeuedEvent event;
1542 HostedStatePublicationContext context(
this, &event);
1544 __atomic_store_n(&g_StatePublicationContext, &context, __ATOMIC_RELEASE);
1545 setStateTransitionHook(hostedStatePublicationHook);
1547 SchedulerState* previousState =
pushState();
1548 const bool pushed = previousState &&
getStateLevel() == (initialStateLevel + 1);
1549 if (previousState) {
1553 setStateTransitionHook(
nullptr);
1554 __atomic_store_n(&g_StatePublicationContext,
static_cast<HostedStatePublicationContext*
>(
nullptr),
1557 const bool publishedSafely = pushed &&
getStateLevel() == initialStateLevel &&
1558 context.calls == 3 && context.failures == 0 &&
1559 event.pendingCount() == 3 &&
hasEvent(&event);
1561 const bool deliveriesCulled =
event.pendingCount() == 0 && !
hasEvent(&event);
1563 return publishedSafely && deliveriesCulled;
1566bool Thread::runHostedStateCleanupRegression() {
1568 if (!clearUserReturnWorkIfIdle() || userReturnWorkPending() || !canSkipUserReturnWork()) {
1571 const auto terminationWorkPending = [
this]() {
1573 !clearUserReturnWorkIfIdle();
1575 HostedStateCleanupOrder order;
1576 HostedStateCleanupItem oldItem{&order, 0};
1577 HostedStateCleanupItem firstItem{&order, 1};
1578 HostedStateCleanupItem secondItem{&order, 2};
1579 HostedStateCleanupItem normalItem{&order, 3};
1580 HostedStateCleanupItem baseItem{&order, 4};
1581 HostedStateCleanupItem levelItem{&order, 5};
1592 armStateCleanup(oldRecord, hostedStateCleanupCallback, &oldItem);
1593 const size_t checkpoint = stateCleanupCheckpoint();
1594 armStateCleanup(firstRecord, hostedStateCleanupCallback, &firstItem);
1595 armAtomicStateCleanup(secondRecord, hostedStateCleanupCallback, &secondItem);
1597 registerFreshTerminationDeferral(checkpointTerminationRecord);
1598 retireDeferredScopesAfter(checkpoint);
1600 const bool checkpointPassed = order.count == 2 && order.values[0] == 2 && order.values[1] == 1 &&
1601 oldRecord.armed && !firstRecord.armed && !secondRecord.armed &&
1603 !userReturnWorkPending() && canSkipUserReturnWork();
1604 disarmStateCleanup(oldRecord);
1606 armStateCleanup(normalRecord, hostedStateCleanupCallback, &normalItem);
1607 disarmStateCleanup(normalRecord);
1608 const bool normalPassed = order.count == 2 && !normalRecord.armed;
1611 const uint64_t temporarySignalMask = originalSignalMask ^ (
static_cast<uint64_t
>(1) << 7);
1612 const size_t temporaryMaskCheckpoint = stateCleanupCheckpoint();
1613 bool temporaryMaskActive =
false;
1615 TemporarySignalMask signalMask(*
this, temporarySignalMask);
1616 temporaryMaskActive =
getSignalMask() == temporarySignalMask;
1617 retireDeferredScopesAfter(temporaryMaskCheckpoint);
1619 const bool temporaryMaskCleanupPassed = temporaryMaskActive &&
1624 const size_t contextCheckpoint = stateCleanupCheckpoint();
1625 bool contextCleanupPassed =
true;
1633 retireDeferredScopesAfter(contextCheckpoint);
1638 armStateCleanup(baseRecord, hostedStateCleanupCallback, &baseItem);
1639 const bool pushed =
pushState() !=
nullptr;
1641 armAtomicStateCleanup(levelRecord, hostedStateCleanupCallback, &levelItem);
1642 registerFreshTerminationDeferral(levelTerminationRecord);
1645 const bool levelPassed = pushed &&
getStateLevel() == initialLevel && order.count == 3 &&
1646 order.values[2] == 5 && baseRecord.armed && !levelRecord.armed &&
1648 !userReturnWorkPending() && canSkipUserReturnWork();
1649 disarmStateCleanup(baseRecord);
1651 registerDeferredScope(terminationRecord,
true,
false);
1652 const bool explicitTerminationDefers = terminationWorkPending();
1653 unregisterDeferredScope(terminationRecord);
1655 !userReturnWorkPending() && canSkipUserReturnWork();
1657 bool pureScopesPassed =
true;
1660 const size_t pureCheckpoint = stateCleanupCheckpoint();
1662 ByteSet(scopeStorage, 0xa5,
sizeof(scopeStorage));
1666 const size_t freshSequence = freshRecord ? freshRecord->sequence : 0;
1667 pureScopesPassed &= freshRecord && freshRecord != initialHead && freshRecord->armed &&
1668 freshRecord->next == initialHead && freshRecord->stateLevel == initialLevel &&
1669 freshSequence > pureCheckpoint && freshRecord->defersTermination &&
1670 !freshRecord->defersEvents && !freshRecord->cleanup &&
1671 !freshRecord->context && terminationWorkPending();
1674 fresh->~TerminationDeferral();
1677 pureScopesPassed &= movedRecord && movedRecord != freshRecord &&
1678 movedRecord->sequence == freshSequence && terminationWorkPending();
1681 ByteSet(scopeStorage, 0x5a,
sizeof(scopeStorage));
1684 __atomic_load_n(&
m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE) == movedRecord;
1685 *disabled = pedigree_std::move(moved);
1689 adoptedRecord && adoptedRecord->sequence == freshSequence && terminationWorkPending();
1691 armStateCleanup(normalRecord, hostedStateCleanupCallback, &normalItem);
1694 *disabled = pedigree_std::move(newer);
1696 __atomic_load_n(&
m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE) == &normalRecord &&
1697 normalRecord.next == adoptedRecord && adoptedRecord &&
1698 adoptedRecord->sequence == freshSequence && terminationWorkPending();
1700 disarmStateCleanup(normalRecord);
1704 __atomic_load_n(&
m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE) == initialHead;
1705 disabled->~TerminationDeferral();
1708 bool nestedWorkPassed =
true;
1712 nestedWorkPassed &= terminationWorkPending();
1713 registerDeferredScope(eventOnlyRecord,
false,
true);
1717 nestedWorkPassed &= terminationWorkPending();
1720 !canSkipUserReturnWork() && !clearUserReturnWorkIfIdle();
1722 unregisterDeferredScope(eventOnlyRecord);
1723 nestedWorkPassed &= !userReturnWorkPending() && canSkipUserReturnWork();
1725 registerDeferredScope(eventOnlyRecord,
true,
true);
1726 nestedWorkPassed &= terminationWorkPending() &&
eventsDeferred();
1727 unregisterDeferredScope(eventOnlyRecord);
1729 canSkipUserReturnWork();
1731 return cleanupDoesNotDeferTermination && checkpointPassed && normalPassed &&
1732 temporaryMaskCleanupPassed && contextCleanupPassed && levelPassed &&
1733 explicitTerminationDefers && explicitTerminationRetired && pureScopesPassed &&
1734 nestedWorkPassed && order.count == 3;
1737bool Thread::runHostedExecStackOwnershipRegression() {
1742 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
1743 if (m_StateLevels[level].m_pUserStack) {
1748 constexpr size_t FakeStackSize = 4 * 4096;
1753 m_StateLevels[0].m_pUserStack = oldBase;
1756 m_StateLevels[0].m_pUserStack =
nullptr;
1763 m_StateLevels[nestedLevel].m_pUserStack = oldNested;
1765 m_StateLevels[MAX_NESTED_EVENTS - 1].m_pUserStack = oldBase;
1768 bool allOldMetadataDiscarded =
true;
1769 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
1770 allOldMetadataDiscarded &= m_StateLevels[level].m_pUserStack ==
nullptr;
1776 const bool replacementOwnedByBase = m_StateLevels[0].m_pUserStack == replacement &&
1777 m_StateLevels[nestedLevel].m_pUserStack ==
nullptr;
1781 m_StateLevels[0].m_pUserStack =
nullptr;
1785 return allOldMetadataDiscarded && replacementOwnedByBase &&
getStateLevel() == 0;
1788void Thread::withDeferredScopeLockForTest(DeferredScopeLockHook hook) {
1789 m_DeferredScopeRegressionLock.acquire();
1793 m_DeferredScopeRegressionLock.release();
1796bool Thread::runHostedEventDeliveryLeaseRegression() {
1801 HostedPrequeuedEvent event;
1807 if (!delivery || delivery.get() != &event ||
hasEvent(&event) || event.pendingCount() != 1) {
1813 HostedDeliveryLeaseContext context(&event);
1815 &context,
nullptr,
false,
true);
1816 waiterA->setName(
"hosted event-delivery lease waiter A");
1818 while (context.entered !=
static_cast<size_t>(1)) {
1822 for (
size_t i = 0; i < 4; ++i) {
1827 waiterInfo.channelOwner == &
event && waiterInfo.queued;
1828 const bool rejectedAfterClose = closePublished && !
sendEvent(&event);
1829 const bool leaseHeld = context.completed == 0 &&
event.pendingCount() == 1;
1832 while (context.completed !=
static_cast<size_t>(1)) {
1836 const bool waiterAJoined = waiterA->
join();
1837 const bool deliveryLeasePassed = closePublished && rejectedAfterClose && leaseHeld &&
1838 waiterAJoined &&
event.pendingCount() == 0;
1840 HostedPrequeuedEvent deferredEvent;
1841 const size_t callsBefore = g_HostedPrequeuedEventCalls;
1842 bool nestedDeferralPassed =
false;
1851 nestedDeferralPassed = g_HostedPrequeuedEventCalls == callsBefore &&
1852 hasEvent(&deferredEvent) && deferredEvent.pendingCount() == 1;
1856 nestedDeferralPassed = nestedDeferralPassed && g_HostedPrequeuedEventCalls == callsBefore &&
1857 hasEvent(&deferredEvent) && deferredEvent.pendingCount() == 1;
1861 nestedDeferralPassed = nestedDeferralPassed && g_HostedPrequeuedEventCalls == (callsBefore + 1) &&
1862 !
hasEvent(&deferredEvent) && deferredEvent.pendingCount() == 0;
1864 const size_t retireCallsBefore = g_HostedSelfRetireCalls;
1865 const size_t retireDestructionsBefore = g_HostedSelfRetireDestructions;
1866 HostedSelfRetireEvent* retiringEvent =
new HostedSelfRetireEvent;
1867 g_pHostedSelfRetireEvent = retiringEvent;
1868 const bool retireQueued =
sendEvent(retiringEvent);
1872 g_pHostedSelfRetireEvent =
nullptr;
1873 delete retiringEvent;
1875 const bool selfRetirePassed = retireQueued && !g_pHostedSelfRetireEvent &&
1876 g_HostedSelfRetireCalls == (retireCallsBefore + 1) &&
1877 g_HostedSelfRetireDestructions == (retireDestructionsBefore + 1);
1879 HostedAdmissionRetireEvent* admissionEvent =
new HostedAdmissionRetireEvent;
1880 HostedAdmissionRetireContext admissionContext(
1881 admissionEvent,
static_cast<size_t>(g_HostedAdmissionRetireDestructions));
1882 g_pHostedAdmissionRetireContext = &admissionContext;
1883 __atomic_store_n(&g_EventAdmissionTarget,
this, __ATOMIC_RELEASE);
1884 __atomic_store_n(&g_EventAdmissionHook, &hostedAdmissionRetireHook, __ATOMIC_RELEASE);
1885 const bool rejectedByConcurrentRetire = !
sendEvent(admissionEvent);
1886 __atomic_store_n(&g_EventAdmissionHook,
static_cast<EventAdmissionHook
>(
nullptr),
1888 __atomic_store_n(&g_EventAdmissionTarget,
static_cast<Thread*
>(
nullptr), __ATOMIC_RELEASE);
1889 g_pHostedAdmissionRetireContext =
nullptr;
1890 const bool admissionRetirePassed =
1891 rejectedByConcurrentRetire && admissionContext.calls == 1 &&
1892 admissionContext.destroyedInsideHook == 0 &&
1893 g_HostedAdmissionRetireDestructions == (admissionContext.destructionsBefore + 1);
1895 return deliveryLeasePassed && nestedDeferralPassed && selfRetirePassed && admissionRetirePassed;
1898bool Thread::runHostedEventShutdownRegression() {
1903 HostedShutdownStableEvent stableEvent;
1904 HostedShutdownStableEvent racingEvent;
1905 HostedShutdownStableEvent postShutdownEvent;
1906 const size_t eventCallsBefore = g_HostedShutdownEventCalls;
1907 const size_t destructionsBefore = g_HostedShutdownEventDestructions;
1908 const size_t threadCallsBefore = g_HostedShutdownThreadCalls;
1911 nullptr,
nullptr,
false,
true,
true);
1912 target->setName(
"hosted event-queue shutdown regression");
1914 const bool stableQueued = target->
sendEvent(&stableEvent);
1915 HostedShutdownDeletableEvent* deletableEvent =
new HostedShutdownDeletableEvent;
1916 const bool deletableQueued = stableQueued && target->
sendEvent(deletableEvent);
1917 if (!deletableQueued) {
1918 delete deletableEvent;
1921 __atomic_store_n(&g_EventAdmissionTarget, target, __ATOMIC_RELEASE);
1923 &g_EventAdmissionHook,
1924 +[](
Thread* admissionTarget) {
1937 const bool rejectedDuringShutdown = !target->
sendEvent(&racingEvent);
1938 __atomic_store_n(&g_EventAdmissionHook,
static_cast<EventAdmissionHook
>(
nullptr),
1940 __atomic_store_n(&g_EventAdmissionTarget,
static_cast<Thread*
>(
nullptr), __ATOMIC_RELEASE);
1942 bool shutdownObserved =
false;
1943 constexpr size_t ShutdownAttempts = 10000;
1944 for (
size_t attempt = 0; attempt < ShutdownAttempts; ++attempt) {
1949 if (shutdownObserved) {
1955 bool rejectedAfterShutdown =
false;
1956 if (shutdownObserved) {
1957 rejectedAfterShutdown = !target->
sendEvent(&postShutdownEvent);
1958 if (!rejectedAfterShutdown) {
1963 const bool joined = target->
join();
1964 return stableQueued && deletableQueued && rejectedDuringShutdown && shutdownObserved &&
1965 rejectedAfterShutdown && joined && stableEvent.pendingCount() == 0 &&
1966 racingEvent.pendingCount() == 0 && postShutdownEvent.pendingCount() == 0 &&
1967 g_HostedShutdownEventCalls == eventCallsBefore &&
1968 g_HostedShutdownEventDestructions == (destructionsBefore + 1) &&
1969 g_HostedShutdownThreadCalls == threadCallsBefore;
1994 return state.m_DeferredSignalMaskRestore ?
state.m_SavedSignalMask :
state.m_SignalMask;
2001 if (
state.m_DeferredSignalMaskRestore) {
2002 state.m_SavedSignalMask = 0;
2003 state.m_DeferredSignalMaskRestore =
false;
2009 if (stateLevel >= MAX_NESTED_EVENTS) {
2010 FATAL(
"Deferred signal mask restored from an invalid Thread state level.");
2014 if (
state.m_DeferredSignalMaskRestore) {
2016 state.m_SavedSignalMask = 0;
2017 state.m_DeferredSignalMaskRestore =
false;
2025 state.m_DispatchedSignalContinuationEpoch = continuationEpoch;
2031 if (!
state.m_DispatchedSignalNumber) {
2036 continuationEpoch =
state.m_DispatchedSignalContinuationEpoch;
2042 uint64_t effectiveSignalMask = 0;
2046 FATAL(
"Thread state changed during exec signal preparation.");
2049 effectiveSignalMask =
2050 state.m_DeferredSignalMaskRestore ?
state.m_SavedSignalMask :
state.m_SignalMask;
2057 for (
size_t level = execStateLevel; level > 0; --level) {
2058 retireDeferredScopes(
false, level - 1);
2063 FATAL(
"Thread state changed during exec signal preparation.");
2069 base.m_TemporarySignalMaskActive =
false;
2070 base.m_TemporarySignalWaitInterrupted =
false;
2071 base.m_DeferredSignalMaskRestore =
false;
2073 base.m_DispatchedSignalContinuationEpoch = 0;
2075 base.m_InterruptionReason = NotInterrupted;
2080size_t Thread::beginTemporarySignalMask(uint64_t signalMask) {
2082 FATAL(
"Temporary signal mask armed for a non-current Thread.");
2087 if (stateLevel >= MAX_NESTED_EVENTS) {
2088 FATAL(
"Temporary signal mask armed on an invalid Thread state level.");
2091 StateLevel&
state = m_StateLevels[stateLevel];
2092 if (
state.m_TemporarySignalMaskActive ||
state.m_DeferredSignalMaskRestore) {
2093 FATAL(
"Thread state already owns a temporary signal mask.");
2096 state.m_SavedSignalMask =
state.m_SignalMask;
2097 state.m_SignalMask = signalMask;
2098 state.m_InterruptionReason = NotInterrupted;
2099 state.m_TemporarySignalWaitInterrupted =
false;
2100 state.m_TemporarySignalMaskActive =
true;
2104bool Thread::finishTemporarySignalMask(
size_t stateLevel,
bool deferForUserReturn) {
2106 if (stateLevel >= MAX_NESTED_EVENTS) {
2107 FATAL(
"Temporary signal mask restored from an invalid Thread state level.");
2110 StateLevel&
state = m_StateLevels[stateLevel];
2111 if (!
state.m_TemporarySignalMaskActive) {
2112 FATAL(
"Thread state has no temporary signal mask to restore.");
2115 const bool interrupted =
state.m_TemporarySignalWaitInterrupted;
2116 bool deferRestore =
false;
2117 if (deferForUserReturn && interrupted && stateLevel ==
m_nStateLevel) {
2121 eventIsDeliverableUnlocked(event, EventSelection::AnyDeliverable)) {
2122 deferRestore =
true;
2128 markUserReturnWorkPending();
2131 state.m_DeferredSignalMaskRestore = deferRestore;
2132 if (!deferRestore) {
2133 state.m_SignalMask =
state.m_SavedSignalMask;
2134 state.m_SavedSignalMask = 0;
2136 state.m_TemporarySignalMaskActive =
false;
2137 state.m_TemporarySignalWaitInterrupted =
false;
2138 if (interrupted &&
state.m_InterruptionReason == InterruptedBySignal) {
2139 state.m_InterruptionReason = NotInterrupted;
2147 return state.m_TemporarySignalMaskActive &&
state.m_TemporarySignalWaitInterrupted &&
2148 state.m_InterruptionReason == InterruptedBySignal;
2153 return m_StateLevels[
m_nStateLevel].m_TemporarySignalMaskActive;
2161 const bool retained =
state.m_TemporarySignalMaskActive &&
2162 state.m_TemporarySignalWaitInterrupted &&
2163 state.m_InterruptionReason == InterruptedBySignal;
2165 state.m_InterruptionReason = NotInterrupted;
2178 if (*it == pEvent) {
2201 if ((*it)->getNumber() == eventNumber) {
2202 Event* pEvent = *it;
2211 for (
auto it : deregisterEvents) {
2212 it->completeDelivery(
this);
2223 if ((*it)->isSignalEvent() && (*it)->getNumber() == signalNumber) {
2224 Event* pEvent = *it;
2233 for (
auto it : deregisterEvents) {
2234 it->completeDelivery(
this);
2239 if (&target ==
this) {
2244 Event* pending =
nullptr;
2248 if ((*it)->isSignalEvent() &&
static_cast<SignalEvent*
>(*it)->isProcessDirected()) {
2271 uint64_t rebindGeneration) {
2277 if (!eventSendLease) {
2291 Event* previous =
nullptr;
2292 if (eventRegistered) {
2297 if ((*it)->isSignalEvent() && (*it)->getNumber() == signalNumber &&
2298 (!rebindGeneration ||
2299 static_cast<SignalEvent*
>(*it)->rebindGeneration() != rebindGeneration) &&
2300 (processDirected < 0 ||
2301 static_cast<SignalEvent*
>(*it)->isProcessDirected() == (processDirected != 0))) {
2305 newSignal->setProcessDirected(oldSignal->isProcessDirected());
2306 newSignal->
setSignalOrigin(oldSignal->getSignalCode(), oldSignal->getSenderProcess(),
2307 oldSignal->getSenderUser());
2309 newSignal->setSignalValue(oldSignal->getSignalValue());
2310 oldSignal->transferDeliveryStateTo(*newSignal);
2311 newSignal->setQueueSequence(oldSignal->queueSequence());
2312 newSignal->setChildStatus(oldSignal->childStatus(), oldSignal->childUserTime(),
2313 oldSignal->childSystemTime());
2314 newSignal->setRebindGeneration(rebindGeneration);
2322 if (eventRegistered && !previous) {
2331 bool drained =
false;
2342 return previous !=
nullptr;
2349 if ((*it)->isSignalEvent() && (*it)->getNumber() == signalNumber &&
2350 (processDirected < 0 ||
2351 static_cast<SignalEvent*
>(*it)->isProcessDirected() == (processDirected != 0))) {
2358bool Thread::acceptingEvents() {
2363void Thread::setSynchronousSignalMask(uint64_t mask) {
2365 m_SynchronousSignalMask = mask;
2368uint64_t Thread::getSynchronousSignalMask() {
2370 return m_SynchronousSignalMask;
2373uint64_t Thread::pendingSignalMask(
bool processOnly) {
2377 if (!event->isSignalEvent() || !event->getNumber() || event->getNumber() > 64) {
2381 if (signal->deliveryActive() && (!processOnly || signal->isProcessDirected())) {
2382 mask |= uint64_t(1) << (signal->getNumber() - 1);
2388uint64_t Thread::pendingSignalOrder(
size_t number,
bool processOnly) {
2390 uint64_t sequence = ~uint64_t(0);
2392 if (!event->isSignalEvent() || event->getNumber() != number)
2395 if (signal->deliveryActive() && (!processOnly || signal->isProcessDirected()) &&
2396 signal->queueSequence() < sequence)
2397 sequence = signal->queueSequence();
2402Event::Delivery Thread::reservePendingSignal(uint64_t mask,
bool processOnly,
2403 uint64_t expectedSequence) {
2408 if (!event->isSignalEvent() || !
event->getNumber() ||
event->getNumber() > 64) {
2412 if (signal->deliveryActive() && (!processOnly || signal->isProcessDirected()) &&
2413 (mask & (uint64_t(1) << (signal->getNumber() - 1))) &&
2414 (selected ==
m_EventQueue.
end() ||
event->getNumber() < (*selected)->getNumber() ||
2415 (
event->getNumber() == (*selected)->getNumber() &&
2416 signal->queueSequence() <
static_cast<SignalEvent*
>(*selected)->queueSequence()))) {
2423 Event*
event = *selected;
2424 if (expectedSequence != ~uint64_t(0) &&
2425 static_cast<SignalEvent*
>(event)->queueSequence() != expectedSequence)
2432 if (!delivery || delivery.m_pThread !=
this || delivery.m_bActive) {
2441 delivery.m_pEvent =
nullptr;
2442 delivery.m_pThread =
nullptr;
2448void Thread::cullSignalSource(
const void* source) {
2453 if ((*it)->isSignalEvent() &&
static_cast<SignalEvent*
>(*it)->deliverySource() == source) {
2461 for (
Event* event : retiring) {
2462 event->completeDelivery(
this);
2467 Event* pResult =
nullptr;
2479 if (!eventIsDeliverableUnlocked(event, selection)) {
2484 }
else if (event->isSignalEvent() && (*selected)->isSignalEvent() &&
2485 (
event->getNumber() < (*selected)->getNumber() ||
2486 (
event->getNumber() == (*selected)->getNumber() &&
2487 static_cast<SignalEvent*
>(event)->queueSequence() <
2488 static_cast<SignalEvent*
>(*selected)->queueSequence()))) {
2491 if (!event->isSignalEvent()) {
2496 pResult = *selected;
2504bool Thread::hasEvents() {
2510bool Thread::eventIsDeliverableUnlocked(
Event* event, EventSelection selection) {
2511 const size_t eventNumber =
event->getNumber();
2512 if (m_UserReturnSignalParked && event->
isSignalEvent() && eventNumber != 9)
2515 (!
static_cast<SignalEvent*
>(event)->deliveryActive() ||
2516 (eventNumber > 0 && eventNumber <= 64 &&
2517 (m_SynchronousSignalMask & (uint64_t(1) << (eventNumber - 1)))))) {
2520 const bool signalInhibited =
2521 event->isSignalEvent() && eventNumber > 0 && eventNumber <= 64 &&
2523 const bool exactUserReturnUnavailable =
2524 (selection == EventSelection::WithoutExactUserReturn &&
2526 (selection != EventSelection::AnyDeliverable && m_SignalFramesRequired &&
2529 bool processBlocksEvent =
false;
2530 if (selection == EventSelection::StoppedProcessKernel) {
2534 processBlocksEvent =
event->getHandlerPrivilege() != Event::HandlerPrivilege::Kernel ||
2535 !
event->isDeliverableWhileProcessSuspended();
2538 processBlocksEvent =
2539 (selection == EventSelection::KernelDeliverable &&
2540 event->getHandlerPrivilege() != Event::HandlerPrivilege::Kernel) ||
2541 (processState != Process::Active &&
2546 !exactUserReturnUnavailable && !processBlocksEvent &&
2547 (
event->getSpecificNestingLevel() == ~0UL ||
2555 bool caughtSignalDeferred =
false;
2559 eventIsDeliverableUnlocked(event, EventSelection::AnyDeliverable)) {
2560 caughtSignalDeferred =
true;
2564 if (!caughtSignalDeferred) {
2570 current.m_InterruptionReason = InterruptedBySignal;
2575 for (
size_t level =
m_nStateLevel + 1; level > 0; --level) {
2576 StateLevel& owner = m_StateLevels[level - 1];
2577 if (!owner.m_TemporarySignalMaskActive) {
2581 owner.m_InterruptionReason = InterruptedBySignal;
2582 owner.m_TemporarySignalWaitInterrupted =
true;
2589 if (eventIsDeliverableUnlocked(*it, selection)) {
2597bool Thread::hasDeliverableEventsUnlocked(EventSelection selection) {
2602 bool wakeThread =
false;
2613 assert(readyScheduler);
2622 if ((*it) == pEvent) {
2634 if ((*it)->getNumber() == eventNumber) {
2645 if (!m_StateLevels[0].m_pKernelStack)
2656 m_pParent->allocateUserRange(Process::UserRegion::Dynamic, THREAD_TLS_SIZE, base);
2658 m_pParent->allocateUserRange(Process::UserRegion::Normal, THREAD_TLS_SIZE, base);
2663 <<
"]: failed to allocate TLS area.");
2670 phys,
reinterpret_cast<void*
>(base),
2676 uint32_t* tlsBase =
reinterpret_cast<uint32_t*
>(
m_pTlsBase);
2678 *tlsBase =
static_cast<uint32_t
>(
m_Id);
2685 <<
"]: allocated TLS area at " <<
m_pTlsBase <<
".");
2688 return reinterpret_cast<uintptr_t
>(
m_pTlsBase);
2695#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2696 TlsResetHook hook = __atomic_load_n(&g_TlsResetHook, __ATOMIC_ACQUIRE);
2697 Thread* hookTarget = __atomic_load_n(&g_TlsResetTarget, __ATOMIC_ACQUIRE);
2698 if (hook && hookTarget ==
this) {
2699 hook(
this, TlsResetBeforeClear, 0);
2704#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2705 if (hook && hookTarget ==
this) {
2706 hook(
this, TlsResetCleared, 0);
2713 Processor::setUserGsBase(0);
2715#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2716 if (hook && hookTarget ==
this) {
2717 hook(
this, TlsResetRemapped, tlsBase);
2733void Thread::setUserGsBase(uintptr_t base) {
2735 m_UserGsBase = base;
2737 Processor::setUserGsBase(base);
2740void Thread::saveUserGsBase() {
2742 m_UserGsBase = Processor::getUserGsBase();
2757 if (pThisThread ==
this) {
2777 bool reapable =
false;
2783 const uintptr_t returnAddress =
reinterpret_cast<uintptr_t
>(__builtin_return_address(0));
2784 WaitQueue::WakeReason reason =
2788 if (reason == WaitQueue::WakeReason::Unwinding ||
2789 reason == WaitQueue::WakeReason::Terminating) {
2793 discardScope.disarm();
2794 discard.claimed =
false;
2809#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2810 JoinOperationHook hook = __atomic_load_n(&g_JoinOperationHook, __ATOMIC_ACQUIRE);
2812 hook(
this, pParent);
2822 bool processOwnsTarget =
false;
2832 processOwnsTarget =
true;
2838 discardScope.disarm();
2839 discard.claimed =
false;
2842 if (!processOwnsTarget) {
2843 requireThreadDestructionContext();
2848 return !processOwnsTarget;
2864 bool finalRelease =
false;
2865 bool finishDetachedRetirement =
false;
2869 FATAL(
"Thread external lease underflow.");
2875 if (finishDetachedRetirement) {
2883#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2884 Thread* hookTarget = __atomic_load_n(&g_ExternalLeaseReleaseTarget, __ATOMIC_ACQUIRE);
2885 if (finalRelease && hookTarget ==
this) {
2886 ExternalLeaseReleaseHook hook = __atomic_load_n(&g_ExternalLeaseReleaseHook, __ATOMIC_ACQUIRE);
2888 hook(
this, ExternalLeaseFinalReleaseUnlocked);
2894#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2895 ExternalLeaseReleaseHook hook = __atomic_load_n(&g_ExternalLeaseReleaseHook, __ATOMIC_ACQUIRE);
2896 if (hookTarget ==
this && hook) {
2897 hook(
this, ExternalLeaseBeforeWaiterWake);
2903 if (!finishDetachedRetirement) {
2914 bool deleteNow =
false;
2941 requireThreadDestructionContext();
2963 const WaitQueue::WakeReason reason = guard.waitForCompletion(
2971 if (!discard->claimed) {
2975 Thread* target = discard->target;
2976 Process* parent = discard->parent;
2977 discard->claimed =
false;
2978 discard->target =
nullptr;
2979 discard->parent =
nullptr;
2993 bool deleteNow =
false;
2994 bool joinInProgress =
false;
3001 "Thread::detach() called while other threads are "
3003 joinInProgress =
true;
3014 if (joinInProgress) {
3030 requireThreadDestructionContext();
3039Thread::StateLevel::StateLevel()
3043 m_pAuxillaryStack(0),
3046 m_SavedSignalMask(0),
3047 m_TemporarySignalMaskActive(false),
3048 m_TemporarySignalWaitInterrupted(false),
3049 m_DeferredSignalMaskRestore(false),
3050 m_DispatchedSignalNumber(0),
3051 m_DispatchedSignalContinuationEpoch(0),
3052 m_bOwnsAlternateSignalStack(false),
3054 m_InterruptionReason(NotInterrupted),
3055 m_bDispatchingWaitEvent(false),
3056 m_ExecutionContext(ExecutionContext::WaitableThread),
3057 m_pRequestQueueCallback(nullptr),
3058 m_bTerminalWaitCancelledBeforeBlock(false)
3061 m_HostedSignalDepth(0)
3064 m_State =
new SchedulerState;
3065 ByteSet(m_State, 0,
sizeof(SchedulerState));
3069Thread::StateLevel::~StateLevel() {
3075 m_pKernelStack(s.m_pKernelStack),
3076 m_pUserStack(s.m_pUserStack),
3077 m_pAuxillaryStack(s.m_pAuxillaryStack),
3079 m_SignalMask(s.m_SignalMask),
3080 m_SavedSignalMask(0),
3081 m_TemporarySignalMaskActive(false),
3082 m_TemporarySignalWaitInterrupted(false),
3083 m_DeferredSignalMaskRestore(false),
3084 m_DispatchedSignalNumber(0),
3085 m_DispatchedSignalContinuationEpoch(0),
3086 m_bOwnsAlternateSignalStack(false),
3088 m_InterruptionReason(s.m_InterruptionReason),
3089 m_bDispatchingWaitEvent(false),
3090 m_ExecutionContext(s.m_ExecutionContext),
3091 m_pRequestQueueCallback(nullptr),
3092 m_bTerminalWaitCancelledBeforeBlock(false)
3095 m_HostedSignalDepth(0)
3098 m_State =
new SchedulerState(*(s.
m_State));
3107 m_TemporarySignalMaskActive =
false;
3108 m_TemporarySignalWaitInterrupted =
false;
3109 m_DeferredSignalMaskRestore =
false;
3111 m_DispatchedSignalContinuationEpoch = 0;
3114 m_InterruptionReason = s.m_InterruptionReason;
3120 m_HostedSignalDepth = 0;
3128 m_StateLevels[interruptedLevel].m_InterruptionReason = InterruptedByTimeout;
3140 interrupted.m_InterruptionReason = InterruptedBySignal;
3148 StateLevel& owner = m_StateLevels[level - 1];
3149 if (!owner.m_TemporarySignalMaskActive) {
3153 owner.m_InterruptionReason = InterruptedBySignal;
3154 owner.m_TemporarySignalWaitInterrupted =
true;
3164 const size_t level = __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE);
3165 if (level >= MAX_NESTED_EVENTS) {
3177 if (!
waiter.snapshotChannel(channel)) {
3180 info.channelOwner = channel.owner;
3181 info.channelValue = channel.value;
3182 info.reason =
waiter.loadReason();
3183 info.stateLevel =
waiter.stateLevel;
3184 info.queued =
waiter.isQueued();
3189 return waiter.loadQueue() == queue && __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE) == level;
3192void Thread::deferEvents() {
3193#if PEDIGREE_LATENCY_ACCOUNTING
3197 m_EventDeferralStarted = LatencyAccounting::active() ? Time::getTicks() : 0;
3201 markUserReturnWorkFlag(UserReturnEventsDeferred);
3204void Thread::resumeEvents() {
3207 FATAL(
"Unbalanced event-delivery deferral.");
3209#if PEDIGREE_LATENCY_ACCOUNTING
3210 Time::Timestamp deferredWall = 0;
3214 if (m_EventDeferralStarted) {
3215 const Time::Timestamp now = Time::getTicks();
3216 deferredWall = now >= m_EventDeferralStarted ? now - m_EventDeferralStarted : 0;
3220 if (__atomic_sub_fetch(&
m_EventDeferralDepth,
static_cast<size_t>(1), __ATOMIC_ACQ_REL) == 0) {
3221 clearUserReturnWorkFlag(UserReturnEventsDeferred);
3222#if PEDIGREE_LATENCY_ACCOUNTING
3223 if (m_EventDeferralStarted) {
3224 LatencyAccounting::recordDeferredWall(deferredWall);
3226 m_EventDeferralStarted = 0;
3231void Thread::deferTermination() {
3235void Thread::resumeTermination() {
3238 FATAL(
"Unbalanced terminal-teardown deferral.");
3244 bool termination,
bool events,
3245 DeferredScopeRecord::Cleanup cleanup,
3250 const size_t level = __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE);
3251 const size_t sequence =
3252 __atomic_add_fetch(&m_NextStateCleanupSequence,
static_cast<size_t>(1), __ATOMIC_ACQ_REL);
3254 FATAL(
"Thread state cleanup sequence exhausted.");
3257 record.stateLevel = level;
3258 record.sequence = sequence;
3259 record.defersTermination = termination;
3260 record.defersEvents = events;
3261 record.cleanup = cleanup;
3262 record.context = context;
3263 record.armed =
true;
3280 DeferredScopeRecord::Cleanup cleanup,
void* context) {
3283 publishDeferredScope(record,
true,
false, cleanup, context);
3286void Thread::registerDeferredScope(
DeferredScopeRecord& record,
bool termination,
bool events) {
3287 if (record.armed || record.next || record.defersTermination || record.defersEvents ||
3288 record.sequence || record.cleanup || record.context) {
3289 FATAL(
"Deferred scope registered more than once.");
3292 publishDeferredScope(record, termination, events,
nullptr,
nullptr);
3295void Thread::armStateCleanup(
DeferredScopeRecord& record, DeferredScopeRecord::Cleanup cleanup,
3298 FATAL(
"State cleanup armed without a callback.");
3301 if (record.armed || record.next || record.defersTermination || record.defersEvents ||
3302 record.sequence || record.cleanup || record.context) {
3303 FATAL(
"State cleanup record armed more than once.");
3306 publishDeferredScope(record,
false,
false, cleanup, context);
3311 if (!record.armed || record.stateLevel >= MAX_NESTED_EVENTS) {
3312 FATAL(
"Deferred scope was not registered on this Thread.");
3318 if (__atomic_load_n(&
m_pDeferredScopes[record.stateLevel], __ATOMIC_ACQUIRE) != &record) {
3319 FATAL(
"Deferred scopes were not released in LIFO order.");
3321 __atomic_store_n(&
m_pDeferredScopes[record.stateLevel], record.next, __ATOMIC_RELEASE);
3324 if (record.defersTermination) {
3325 resumeTermination();
3327 if (record.defersEvents) {
3337 unpublishDeferredScope(record,
true);
3341 unpublishDeferredScope(record,
false);
3347 if (!record.armed || !record.defersTermination || record.defersEvents || record.cleanup ||
3348 record.stateLevel >= MAX_NESTED_EVENTS) {
3349 FATAL(
"Invalid termination deferral retirement.");
3355 while (current && current != &record) {
3357 current = current->next;
3360 FATAL(
"Termination deferral was absent from its Thread.");
3364 previous->next = record.next;
3366 __atomic_store_n(&
m_pDeferredScopes[record.stateLevel], record.next, __ATOMIC_RELEASE);
3368 resumeTermination();
3375 if (&from == &to || !from.armed || from.stateLevel >= MAX_NESTED_EVENTS) {
3376 FATAL(
"Moved termination deferral was not registered.");
3378 if (!from.defersTermination || from.defersEvents || from.cleanup || to.armed || to.next ||
3379 to.defersTermination || to.defersEvents || to.sequence || to.cleanup || to.context) {
3380 FATAL(
"Invalid termination deferral move.");
3389 while (current && current != &from) {
3391 current = current->next;
3394 FATAL(
"Moved termination deferral was absent from its Thread.");
3399 previous->next = &to;
3408void Thread::retireDeferredScopes(
bool allStateLevels,
size_t stateLevel) {
3409 retireDeferredScopesMatching(allStateLevels, stateLevel,
false, 0);
3412size_t Thread::stateCleanupCheckpoint() {
3413 return __atomic_load_n(&m_NextStateCleanupSequence, __ATOMIC_ACQUIRE);
3416void Thread::retireDeferredScopesAfter(
size_t checkpoint) {
3417 retireDeferredScopesMatching(
true, 0,
true, checkpoint);
3420void Thread::retireDeferredScopesMatching(
bool allStateLevels,
size_t stateLevel,
3421 bool newerThanCheckpoint,
size_t checkpoint) {
3425 if (!allStateLevels && stateLevel >= MAX_NESTED_EVENTS) {
3426 FATAL(
"State cleanup retirement has an invalid level.");
3434 size_t candidateLevel = 0;
3436 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
3437 if (!allStateLevels && level != stateLevel) {
3442 if (!head || (newerThanCheckpoint && head->sequence <= checkpoint)) {
3445 if (!head->armed || head->stateLevel != level || !head->sequence) {
3446 FATAL(
"Corrupt Thread state cleanup publication.");
3448 if (!candidate || head->sequence > candidate->sequence) {
3450 candidateLevel = level;
3459 if (!__atomic_compare_exchange_n(&
m_pDeferredScopes[candidateLevel], &expected, candidate->next,
3460 false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
3464 if (candidate->defersTermination) {
3465 resumeTermination();
3467 if (candidate->defersEvents) {
3470 candidate->armed =
false;
3471 candidate->next =
nullptr;
3473 retiredTail->next = candidate;
3475 retired = candidate;
3477 retiredTail = candidate;
3484 DeferredScopeRecord::Cleanup cleanup = retired->cleanup;
3485 void* context = retired->context;
3495 AtomicStateCleanupRecord::Cleanup cleanup,
void* context) {
3497 FATAL(
"Interrupt/exception cleanup armed for a non-current Thread.");
3499 armStateCleanup(record, cleanup, context);
3503size_t Thread::enterHostedSignalHandler() {
3504 const size_t level = __atomic_load_n(&
m_nStateLevel, __ATOMIC_ACQUIRE);
3505 __atomic_add_fetch(&m_StateLevels[level].m_HostedSignalDepth, 1, __ATOMIC_ACQ_REL);
3509void Thread::leaveHostedSignalHandler(
size_t stateLevel) {
3510 if (
UNLIKELY(stateLevel >= MAX_NESTED_EVENTS)) {
3511 FATAL_NOLOCK(
"Hosted signal frame recorded an invalid state level");
3515 const size_t previous =
3516 __atomic_fetch_sub(&m_StateLevels[stateLevel].m_HostedSignalDepth, 1, __ATOMIC_ACQ_REL);
3518 __atomic_store_n(&m_StateLevels[stateLevel].m_HostedSignalDepth, 0, __ATOMIC_RELEASE);
3519 FATAL_NOLOCK(
"Hosted Thread signal-frame depth underflowed");
3526 FATAL(
"Interrupt/exception cleanup disarmed for a non-current Thread.");
3528 disarmStateCleanup(record);
3532 __atomic_store_n(&m_pScheduler, pScheduler, __ATOMIC_RELEASE);
3537 FATAL(
"Thread state stack freed with an armed cleanup record.");
3539 if (m_StateLevels[level].m_TemporarySignalMaskActive) {
3540 FATAL(
"Thread state stack freed with an active temporary signal mask.");
3545 if (__atomic_load_n(&m_StateLevels[level].m_HostedSignalDepth, __ATOMIC_ACQUIRE)) {
3546 FATAL(
"Thread state stack freed with a live hosted signal frame.");
3550 if (m_StateLevels[level].m_Waiter.loadQueue()) {
3551 FATAL(
"Thread state stack was cleaned while still in a wait queue.");
3554 if (m_StateLevels[level].m_pKernelStack) {
3557 }
else if (m_StateLevels[level].m_pAuxillaryStack) {
3562 if (m_StateLevels[level].m_pUserStack &&
m_pParent) {
3566 m_StateLevels[level].m_pUserStack = 0;
3571 m_StateLevels[level].m_TemporarySignalWaitInterrupted =
false;
3573 m_StateLevels[level].m_DispatchedSignalContinuationEpoch = 0;
3581 bool becameReady =
false;
3582 bool queuedBeforeStart =
false;
3586 __atomic_store_n(&m_UnwindState, ut, __ATOMIC_RELEASE);
3589 markUserReturnWorkPending();
3592 terminating ? WaitQueue::WakeReason::Terminating : WaitQueue::WakeReason::Unwinding,
3598 assert(readyScheduler);
3600 }
else if (queuedBeforeStart) {
3613 const uint64_t request =
static_cast<uint32_t
>(signal) | (
static_cast<uint64_t
>(1) << 32);
3619 const uint64_t value =
3622 ? Subsystem::ExitCause::Signal
3623 : Subsystem::ExitCause::Normal};
3628 size_t expected = 0;
3630 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
3631 FATAL_NOLOCK(
"Nested subsystem exception reached an occupied deferred slot");
3635 m_DeferredSubsystemExceptionType = type;
3636 m_DeferredSubsystemExceptionFaultAddress = faultAddress;
3637 m_DeferredSubsystemExceptionErrorCode = errorCode;
3639 markUserReturnWorkFlag(UserReturnDeferredException);
3644 uintptr_t& errorCode) {
3649 type = m_DeferredSubsystemExceptionType;
3650 faultAddress = m_DeferredSubsystemExceptionFaultAddress;
3651 errorCode = m_DeferredSubsystemExceptionErrorCode;
3653 clearUserReturnWorkFlag(UserReturnDeferredException);
3659 readyScheduler =
nullptr;
3661 if (!
waiter.loadQueue() ||
waiter.loadReason() != WaitQueue::WakeReason::Waiting) {
3665 waiter.storeReason(reason);
3669 __atomic_store_n(&m_ReadyPublicationPending,
true, __ATOMIC_RELEASE);
3670 readyScheduler =
waiter.scheduler;
3671 assert(readyScheduler);
3677bool Thread::hasActiveWaitUnlocked()
const {
3681bool Thread::hasActiveWaitAtAnyLevel()
const {
3682 for (
size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
3683 if (m_StateLevels[level].m_Waiter.loadQueue()) {
3690bool Thread::activeWaitPendingUnlocked()
const {
3692 return waiter.loadQueue() &&
waiter.loadReason() == WaitQueue::WakeReason::Waiting;
3696 assert(level < MAX_NESTED_EVENTS);
3698 assert(!
state.m_Waiter.loadQueue());
3699 assert(
state.m_Waiter.loadReason() == WaitQueue::WakeReason::Terminating);
3700 state.m_bTerminalWaitCancelledBeforeBlock =
true;
3703bool Thread::consumeTerminalWaitCancelledBeforeBlockUnlocked() {
3705 if (!
state.m_bTerminalWaitCancelledBeforeBlock) {
3712 return !
state.m_Waiter.loadQueue() &&
3713 state.m_Waiter.loadReason() == WaitQueue::WakeReason::Terminating;
3716void Thread::clearTerminalWaitCancelledBeforeBlockUnlocked(
size_t level) {
3717 assert(level < MAX_NESTED_EVENTS);
3724 Metrics::increment(Metrics::ThreadReapable);
3729 bool externalLeasesDrained =
false;
3732 externalLeasesDrained =
3735 const bool deleteNow =
3747 return m_UserspacePid ? m_UserspacePid->id(space) : 0;
bool registerThread(Thread *thread)
void completeDelivery(Thread *thread)
HandlerPrivilege getHandlerPrivilege() const
void deregisterThread(Thread *thread)
virtual bool isSignalEvent() const
virtual size_t getNumber()=0
virtual bool isDeliverableWhileProcessSuspended() const
virtual size_t serialize(uint8_t *pBuffer)=0
bool test(size_t n) const
::Iterator< T, node_t > Iterator
static NMFaultHandler & instance()
static bool inheritCurrentThreadFpuState(class Thread *thread)
SchedulingAlgorithm * m_pSchedulingAlgorithm
void publishReadyFromWait(Thread *pThread)
virtual physical_uintptr_t allocatePage(size_t pageConstraints=0)=0
static PhysicalMemoryManager & instance()
virtual void freePage(physical_uintptr_t page)=0
size_t getUserspaceId() const
VirtualAddressSpace * getAddressSpace()
void removeThread(Thread *pThread)
void transferExecProcessSignals(Thread *pThread)
void threadExiting(Thread *pThread)
size_t addThread(Thread *pThread)
static bool getInterrupts()
static void setTlsBase(uintptr_t newBase)
static ProcessorInformation & information()
static ExecutionContext executionContext()
static void setInterrupts(bool bEnable)
void addThread(Thread *pThread, Thread::ThreadStartFunc pStartFunction, void *pParam, bool bUsermode, void *pStack)
void recordCpuTime(const Thread &thread, CpuTimeMode mode, Time::Timestamp elapsed)
void removeThread(Thread *pThread)
static Scheduler & instance()
void addThread(Thread *pThread, PerProcessorScheduler &PPSched)
virtual void threadStatusChanged(Thread *pThread)=0
static SharedPointer< T > allocate(Args...)
void setSignalOrigin(int32_t signalCode, int32_t senderProcess, uint32_t senderUser)
void setContinuationEpoch(size_t continuationEpoch)
bool acquire(bool recurse=false, bool safe=true)
virtual void exit(int code, ExitCause cause=ExitCause::Normal)=0
ALWAYS_INLINE void recordAtInterruptDisabled(CpuTimeMode mode, Time::Timestamp now, size_t processor=0)
ALWAYS_INLINE Time::Timestamp elapsedAtInterruptDisabled(CpuTimeMode mode, Time::Timestamp now, size_t processor=0)
size_t m_DeferredSubsystemExceptionState
ThreadTimeAccounting m_TimeAccounting
bool m_bDetachedRetirementClaimed
void discardUserStackMetadataForExec()
bool hasActiveTemporarySignalMask()
void recordTime(CpuTimeMode mode)
void unlinkWaitsForStackDiscard()
Time::Timestamp m_UserTime
void setTlsBase(uintptr_t base)
void accountTimerTick(Time::Timestamp delta, bool kernelMode)
void setUnwindState(UnwindType ut)
CpuTimeMode currentTimeAccountingMode() const
void wakeForDeliverableEvents()
AlternateSignalStack m_AlternateSignalStack
@ Continue
No unwind necessary, carry on as normal.
@ TerminateThread
Exit only this thread during Process exit.
@ Exit
Exit the owning process at the next safe boundary.
void publishTimeAccounting(CpuTimeMode mode, Time::Timestamp elapsed)
static void discardJoin(void *context)
bool transferProcessSignalsTo(Thread &target)
size_t m_ActiveSyscalls[serviceEnd]
bool interruptWaitUnlocked(WaitQueue::WakeReason reason, PerProcessorScheduler *&readyScheduler)
DeferredScopeRecord * m_pDeferredScopes[MAX_NESTED_EVENTS]
void * getKernelStackBase(size_t *size) const
void markSignalInterruptedWait()
AffinityResult waitAffinity(uint64_t generation)
bool replaceSignalEvent(size_t signalNumber, Event *replacement, int processDirected=-1, uint64_t rebindGeneration=0)
void markTimeoutInterruptedWait()
void restoreDeferredSignalMask(size_t stateLevel)
void cleanStateLevel(size_t level)
bool hasSignalEvent(size_t signalNumber, int processDirected=-1)
bool getWaitDebugInfo(WaitDebugInfo &info)
bool hasEvent(Event *pEvent)
static void threadExited() NORETURN
bool deferSubsystemException(size_t type, uintptr_t faultAddress, uintptr_t errorCode)
void deferSignalExit(int signal)
bool m_bSubsystemExitNotified
size_t m_EventDeferralDepth
void commitSignalHandlerMask(uint64_t mask)
void waitForEvent(WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
WaitQueue m_ExternalLeaseWaiters
MUST_USE_RESULT Event::Delivery getNextEvent(EventSelection selection=EventSelection::AnyDeliverable)
int(* ThreadStartFunc)(void *)
bool eventsDeferred() const
void allocateStackAtLevel(size_t stateLevel)
UnwindType getUnwindState()
void cullEvent(Event *pEvent)
bool retainTemporarySignalWaitInterruptionOrClear()
void setClearChildTid(uintptr_t address)
DeferredThreadReapNode m_DeferredReapNode
bool hasEventsUnlocked(EventSelection selection=EventSelection::AnyDeliverable)
void trackTime(CpuTimeMode mode)
void setScheduler(class PerProcessorScheduler *pScheduler)
ExecutionContext executionContext() const
Process * getParent() const
bool eventNeedsUserReturnFrameUnlocked(Event *event) const
void closeExternalLeaseAdmission()
void popState(bool clean=true)
void prepareSignalStateForExec()
void cullSignalEvent(size_t signalNumber)
void setSignalMask(uint64_t mask)
class PerProcessorScheduler * getScheduler() const
Spinlock m_ExternalLeaseLock
Thread(Process *pParent, ThreadStartFunc pStartFunction, void *pParam, void *pStack=0, bool semiUser=false, bool bDontPickCore=false, bool delayedStart=false, const ThreadPlacement *placement=nullptr)
bool waitForEventOrSignalInterruption(WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
AffinityResult requestAffinity(const CpuAffinityMask &mask, uint64_t &generation)
DeferredProcessExit takeDeferredProcessExit()
bool hasTemporarySignalWaitInterruption()
size_t getUserspaceTaskId(const UserspacePidNamespace *space=nullptr) const
uint64_t getSignalMaskForReturnFrame()
bool beginExternalLease()
bool isTerminationDeferred() const
size_t m_EventSendersInFlight
AffinityResult completeAffinityAtSafePoint(bool *waited=nullptr)
bool getCurrentSignalDelivery(size_t &signalNumber, size_t &continuationEpoch)
void setCurrentSignalDelivery(size_t signalNumber, size_t continuationEpoch)
SchedulerState * pushState()
bool m_bExternalLeaseAdmissionClosed
bool sendEvent(Event *pEvent)
void inhibitEvent(size_t eventNumber, bool bInhibit)
void pokeState(size_t stateLevel, SchedulerState &state)
void markTerminalWaitCancelledBeforeBlockUnlocked(size_t level)
void notifySubsystemExit()
uintptr_t m_ClearChildTid
size_t getStateLevel() const
bool m_bExternalLeaseReleaseInProgress
uint64_t m_DeferredProcessExitRequest
bool joinInternal(bool completion)
WaitQueue m_EventSenderDrainWaiters
size_t m_TerminationDeferralDepth
void closeExternalLeaseAdmissionAndDrain()
bool takeDeferredSubsystemException(size_t &type, uintptr_t &faultAddress, uintptr_t &errorCode)
void markDeferredUserReturnSignalInterruption()
List< Event * > m_EventQueue
void adoptInitialUserStackForExec(VirtualAddressSpace::Stack *stack)
void deferProcessExit(int code)
size_t m_CurrentTimeAccountingMode
void abandonCurrentState(bool clean=false)
void transitionTime(CpuTimeMode from, CpuTimeMode to, bool interruptsAlreadyDisabled=false)
A vector / dynamic array.
virtual void freeStack(Stack *pStack)=0
static const size_t RuntimeMapping
virtual Stack * allocateStack()=0
virtual uintptr_t getDynamicStart() const
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
virtual bool isMapped(void *virtualAddress)=0
virtual bool getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
static const size_t Write
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
virtual void unmap(void *virtualAddress)=0
MUST_USE_RESULT WakeReason waitForCompletion(const Channel &channel=Channel(), size_t debugState=0, uintptr_t debugAddress=0)
Iterator erase(Iterator &Iter)
void pushFront(const T &value)
void pushBack(const T &value)
void pushBack(const T &value)
size_t m_DispatchedSignalNumber
VirtualAddressSpace::Stack * m_pKernelStack
WaitQueue::Waiter m_Waiter
SharedPointer< ExtensibleBitmap > m_InhibitMask
uint64_t m_SavedSignalMask
RequestQueueCallbackScope * m_pRequestQueueCallback
bool m_bOwnsAlternateSignalStack
ExecutionContextState m_ExecutionContext
bool m_bDispatchingWaitEvent
VirtualAddressSpace::Stack * m_pAuxillaryStack
bool m_bTerminalWaitCancelledBeforeBlock