The Pedigree Project 0.1
Thread.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <config.h>
21
22#if THREADS
23
24#include "pedigree/kernel/ActivityDiagnostics.h"
25#if PEDIGREE_LATENCY_ACCOUNTING
26#include "pedigree/kernel/LatencyAccounting.h"
27#endif
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"
52
53Thread::SecurityStateRef Thread::securityState() {
55 return m_SecurityState;
56}
57
58void Thread::setSecurityState(const SecurityStateRef& state) {
59 SecurityStateRef previous;
60 {
62 previous = pedigree_std::move(m_SecurityState);
63 m_SecurityState = state;
64 __atomic_store_n(&m_HasSecurityState, bool(state), __ATOMIC_RELEASE);
65 }
66}
67
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.");
72 }
73 if (m_pThread) {
74 m_pThread->armStateCleanup(m_Record, cleanup, context);
75 }
76}
77
78Thread::StackDiscardScope::~StackDiscardScope() {
79 disarm();
80}
81
82void Thread::StackDiscardScope::disarm() {
83 if (m_pThread) {
84 m_pThread->disarmStateCleanup(m_Record);
85 m_pThread = nullptr;
86 }
87}
88
89Thread::TemporarySignalMask::TemporarySignalMask(Thread& thread, uint64_t signalMask)
90 : m_pThread(&thread), m_StateLevel(0), m_Record() {
91 const bool interruptsWereEnabled = Processor::getInterrupts();
93 m_StateLevel = thread.beginTemporarySignalMask(signalMask);
94 thread.armStateCleanup(m_Record, &TemporarySignalMask::discard, this);
95 Processor::setInterrupts(interruptsWereEnabled);
96}
97
98Thread::TemporarySignalMask::~TemporarySignalMask() {
99 if (m_pThread) {
100 finish();
101 }
102}
103
105 if (!m_pThread) {
106 FATAL("Temporary signal mask restored more than once.");
107 }
108
109 const bool interruptsWereEnabled = Processor::getInterrupts();
111 const bool interrupted = m_pThread->finishTemporarySignalMask(m_StateLevel);
112 m_pThread->disarmStateCleanup(m_Record);
113 m_pThread = nullptr;
114 Processor::setInterrupts(interruptsWereEnabled);
115 return interrupted;
116}
117
118void Thread::TemporarySignalMask::discard(void* context) {
119 TemporarySignalMask* scope = reinterpret_cast<TemporarySignalMask*>(context);
120 if (!scope || !scope->m_pThread) {
121 FATAL("Invalid temporary signal mask discard.");
122 }
123
124 const bool interruptsWereEnabled = Processor::getInterrupts();
126 scope->m_pThread->finishTemporarySignalMask(scope->m_StateLevel, false);
127 scope->m_pThread = nullptr;
128 Processor::setInterrupts(interruptsWereEnabled);
129}
130
131#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
132namespace {
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;
144
145struct HostedStateCleanupOrder {
146 size_t values[8] = {};
147 size_t count = 0;
148};
149
150struct HostedStateCleanupItem {
151 HostedStateCleanupOrder* order;
152 size_t value;
153};
154
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;
159 }
160}
161
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);
165 if (hook) {
166 hook(window, thread, previousLevel, nextLevel);
167 }
168}
169} // namespace
170#endif
171
172namespace {
173#if HOSTED
174// The raw userspace return path needs one stack for its ordinary tail and a
175// second for the first kernel Event it may dispatch. Deeper Events are already
176// ordinary thread work and retain the existing lazy allocation behaviour.
177constexpr size_t HostedPreallocatedUserStateLevel = 2;
178static_assert(MAX_NESTED_EVENTS > HostedPreallocatedUserStateLevel,
179 "Hosted return-tail state levels exceed the Thread nesting limit");
180#endif
181
182void requireThreadDestructionContext() {
183 if (Processor::executionContext() != ExecutionContext::WaitableThread ||
185 FATAL_NOLOCK("Thread destruction requires an IRQ-enabled WaitableThread boundary.");
186 }
187}
188
189class CpuTimeSample {
190 public:
191 explicit CpuTimeSample(bool interruptsAlreadyDisabled = false)
192 : timestamp(0),
193 processor(0),
194 m_InterruptsWereEnabled(false),
195 m_RestoreInterrupts(!interruptsAlreadyDisabled) {
196 if (!interruptsAlreadyDisabled) {
197 m_InterruptsWereEnabled = Processor::getInterrupts();
199 }
200
201 // Keep interrupts masked until the paired baseline/publication update
202 // is complete, so migration cannot invalidate this CPU-clock sample.
203 const auto sample = Time::sampleCpuTime();
204 processor = sample.processor;
205 timestamp = sample.timestamp;
206 }
207
208 ~CpuTimeSample() {
209 if (m_RestoreInterrupts) {
210 Processor::setInterrupts(m_InterruptsWereEnabled);
211 }
212 }
213
214 Time::Timestamp timestamp;
215 size_t processor;
216
217 private:
218 bool m_InterruptsWereEnabled;
219 bool m_RestoreInterrupts;
221};
222} // namespace
223
224Thread::Thread(Process* pParent, ThreadStartFunc pStartFunction, void* pParam, void* pStack,
225 bool semiUser, bool bDontPickCore, bool delayedStart,
226 const ThreadPlacement* placement)
227 : m_pParent(pParent), m_DeferredReapNode(this) {
228 if (pParent == 0) {
229 FATAL("Thread::Thread(): Parent process was NULL!");
230 }
231 initialisePlacement(placement);
232
233 // Initialise our kernel stack.
235
236 // Initialise state level zero
237 m_StateLevels[0].m_pAuxillaryStack = 0;
239
240 Thread* pCurrent = Processor::information().getCurrentThread();
241 if (pCurrent && pCurrent->getParent() == pParent) {
242 m_StateLevels[0].m_SignalMask = pCurrent->m_StateLevels[pCurrent->m_nStateLevel].m_SignalMask;
243 }
244
245 // If we've been given a user stack pointer, we are a user mode thread.
246 bool bUserMode = true;
247 void* requestedStack = pStack;
248 if (pStack == 0) {
249 bUserMode = false;
250 VirtualAddressSpace::Stack* kernelStack = m_StateLevels[0].m_pAuxillaryStack =
251 m_StateLevels[0].m_pKernelStack;
252 m_StateLevels[0].m_pKernelStack = 0;
253
254 if (kernelStack)
255 pStack = kernelStack->getTop();
256 }
257
258 if (semiUser) {
259 // Still have a kernel stack for when we jump to user mode, but start
260 // the thread in kernel mode first.
261 bUserMode = false;
262
263 // If no stack was given and we allocated, extract that allocated stack
264 // back out again so we have a kernel stack proper.
265 if (!requestedStack) {
266 m_StateLevels[0].m_pKernelStack = m_StateLevels[0].m_pAuxillaryStack;
267 }
268 }
269
270#if HOSTED
271 if (requestedStack || semiUser) {
272 // A hosted user IRQ reaches its return tail with allocation forbidden.
273 // Guarantee the tail and its first Event stack before the Thread is
274 // visible to the scheduler without reserving every possible nesting.
275 for (size_t level = 1; level <= HostedPreallocatedUserStateLevel; ++level) {
277 m_StateLevels[level].m_InhibitMask = m_StateLevels[0].m_InhibitMask;
278 }
279 }
280#endif
281
282 m_pParent->inheritFilesystemIds(
283 *this, pCurrent && pCurrent->getParent() == pParent ? pCurrent : nullptr);
284 m_Id = m_pParent->addThread(this);
285
286 // Firstly, grab our lock so that the scheduler cannot preemptively load
287 // balance us while we're starting.
288 m_Lock.acquire();
289
290 if (delayedStart || getUnwindState() == Thread::TerminateThread) {
291 m_Status = Created;
292 }
293
294 // Add to the scheduler
295 if (!bDontPickCore || placement) {
296 ProcessorThreadAllocator::instance().addThread(this, pStartFunction, pParam, bUserMode, pStack);
297 } else {
299 Processor::information().getScheduler().addThread(this, pStartFunction, pParam, bUserMode,
300 pStack);
301 }
302}
303
305 : m_pParent(pParent),
306 m_DeferredReapNode(this),
307 m_pScheduler(&Processor::information().getScheduler()) {
308 if (pParent == 0) {
309 FATAL("Thread::Thread(): Parent process was NULL!");
310 }
311 m_pParent->inheritFilesystemIds(*this, nullptr);
312 m_Id = m_pParent->addThread(this);
313
314 // Initialise our kernel stack.
315 // Kernel-mode threads use the auxiliary stack allocated above.
316
317 // Still add the idle thread to the Scheduler for things like
318 // threadInSchedule
319 Scheduler::instance().addThread(this, *m_pScheduler);
320}
321
322Thread::Thread(Process* pParent, SyscallState& state, bool delayedStart,
323 const ThreadPlacement* placement)
324 : m_pParent(pParent), m_DeferredReapNode(this) {
325 if (pParent == 0) {
326 FATAL("Thread::Thread(): Parent process was NULL!");
327 }
328 initialisePlacement(placement);
329
330 // Initialise our kernel stack.
331 // m_pKernelStack =
332 // VirtualAddressSpace::getKernelAddressSpace().allocateStack();
334
335 // Initialise state level zero
337#if HOSTED
338 for (size_t level = 1; level <= HostedPreallocatedUserStateLevel; ++level) {
340 m_StateLevels[level].m_InhibitMask = m_StateLevels[0].m_InhibitMask;
341 }
342#endif
343
344 Thread* pCurrent = Processor::information().getCurrentThread();
345 if (pCurrent) {
346 m_StateLevels[0].m_SignalMask = pCurrent->m_StateLevels[pCurrent->m_nStateLevel].m_SignalMask;
347
348 // A forked process inherits its alternate signal stack. A new thread
349 // sharing the same process starts with the stack disabled.
350 if (pCurrent->getParent() != pParent) {
352 }
353
354#if X64
356#endif
357 }
358
359 m_pParent->inheritFilesystemIds(*this, pCurrent);
360 m_Id = m_pParent->addThread(this);
361
362 // SyscallState variant has to be called from the parent thread, so this is
363 // OK to do.
364 if (pCurrent && pCurrent->m_bTlsBaseOverride) {
365 // Override our TLS base too (but this will be in the copied address
366 // space).
367 m_bTlsBaseOverride = true;
368 m_pTlsBase = pCurrent->m_pTlsBase;
369 }
370#if X64 && !HOSTED
371 m_UserGsBase = state.getUserEntryMetadata().gsBase;
372#endif
373
374 m_Lock.acquire();
375
376 if (delayedStart || getUnwindState() == Thread::TerminateThread) {
377 m_Status = Created;
378 }
379
380 // Now we are ready to go into the scheduler.
381 ProcessorThreadAllocator::instance().addThread(this, state);
382}
383
384void Thread::recordTime(CpuTimeMode mode) {
385 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
386 const CpuTimeSample sample;
387 m_TimeAccounting.recordAtInterruptDisabled(mode, sample.timestamp, sample.processor);
388 }
389 __atomic_store_n(&m_CurrentTimeAccountingMode, static_cast<size_t>(mode), __ATOMIC_RELEASE);
390}
391
392void Thread::trackTime(CpuTimeMode mode) {
393 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
394 const CpuTimeSample sample;
395 const Time::Timestamp elapsed =
396 m_TimeAccounting.elapsedAtInterruptDisabled(mode, sample.timestamp, sample.processor);
397 if (elapsed) {
398 publishTimeAccounting(mode, elapsed);
399 }
400 } else {
401 (void)mode;
402 }
403}
404
405void Thread::transitionTime(CpuTimeMode from, CpuTimeMode to, bool interruptsAlreadyDisabled) {
406 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
407 const CpuTimeSample sample(interruptsAlreadyDisabled);
408 const Time::Timestamp elapsed =
409 m_TimeAccounting.elapsedAtInterruptDisabled(from, sample.timestamp, sample.processor);
410 m_TimeAccounting.recordAtInterruptDisabled(to, sample.timestamp, sample.processor);
411 __atomic_store_n(&m_CurrentTimeAccountingMode, static_cast<size_t>(to), __ATOMIC_RELEASE);
412 if (elapsed) {
413 publishTimeAccounting(from, elapsed);
414 }
415 } else {
416 (void)from;
417 (void)interruptsAlreadyDisabled;
418 __atomic_store_n(&m_CurrentTimeAccountingMode, static_cast<size_t>(to), __ATOMIC_RELEASE);
419 }
420}
421
422void Thread::accountTimerTick(Time::Timestamp delta, bool kernelMode) {
423 if constexpr (PEDIGREE_TIME_ACCOUNTING && PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
424 // Interrupt entry has already changed the logical mode. Only the saved
425 // frame tells us which mode was running when the timer arrived.
426 if (delta && m_pParent) {
427 publishTimeAccounting(kernelMode ? CpuTimeMode::Kernel : CpuTimeMode::User, delta);
428 }
429 } else {
430 (void)delta;
431 (void)kernelMode;
432 }
433}
434
435void Thread::publishTimeAccounting(CpuTimeMode mode, Time::Timestamp elapsed) {
436 Time::Timestamp* total = mode == CpuTimeMode::User ? &m_UserTime : &m_KernelTime;
437#if X64
438 // IRQ masking and scheduler ownership exclude writers on other CPUs. Keep
439 // this one instruction so an NMI cannot interleave a load/add/store sequence.
440 asm volatile("addq %1, %0" : "+m"(*total) : "r"(elapsed) : "cc");
441#else
442 __atomic_fetch_add(total, elapsed, __ATOMIC_RELAXED);
443#endif
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);
449 }
450 }
451#endif
452#if PEDIGREE_LATENCY_ACCOUNTING
453 if (eventsDeferred()) {
454 LatencyAccounting::recordDeferredCpu(elapsed);
455 }
456#endif
457 m_pParent->reportTimeAccounting(elapsed);
458 Scheduler::instance().recordCpuTime(*this, mode, elapsed);
459}
460
461#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
462void Thread::publishTimeAccountingForHostedTest(Time::Timestamp user, Time::Timestamp system) {
463 const bool interruptsWereEnabled = Processor::getInterrupts();
465 publishTimeAccounting(CpuTimeMode::User, user);
466 publishTimeAccounting(CpuTimeMode::Kernel, system);
467 Processor::setInterrupts(interruptsWereEnabled);
468}
469#endif
470
472 return static_cast<CpuTimeMode>(__atomic_load_n(&m_CurrentTimeAccountingMode, __ATOMIC_ACQUIRE));
473}
474
476 {
480 FATAL(
481 "Thread destroyed before external leases were closed and "
482 "drained.");
483 }
484 }
485
486 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
487 if (__atomic_load_n(&m_pDeferredScopes[level], __ATOMIC_ACQUIRE)) {
488 FATAL("Thread destroyed with armed state cleanup records.");
489 }
490 }
491 for (size_t service = 0; service < serviceEnd; ++service) {
492 if (__atomic_load_n(&m_ActiveSyscalls[service], __ATOMIC_ACQUIRE)) {
493 FATAL("Thread destroyed with an admitted syscall.");
494 }
495 }
496 if (__atomic_load_n(&m_TerminationDeferralDepth, __ATOMIC_ACQUIRE) ||
497 __atomic_load_n(&m_EventDeferralDepth, __ATOMIC_ACQUIRE)) {
498 FATAL("Thread destroyed with active deferral scopes: terminal="
499 << Dec << __atomic_load_n(&m_TerminationDeferralDepth, __ATOMIC_ACQUIRE)
500 << ", event=" << __atomic_load_n(&m_EventDeferralDepth, __ATOMIC_ACQUIRE) << ".");
501 }
502
503 // Before removing from the scheduler, terminate if needed.
504 if (!m_bShutdown) {
505 shutdown();
506 }
507
508 // Clean up allocated stacks at each level.
509 for (size_t i = 0; i < MAX_NESTED_EVENTS; i++) {
511 }
512
513 // Clean up TLS base.
515 // Unmap the TLS base.
517 physical_uintptr_t phys = 0;
518 size_t flags = 0;
522 }
523
524 // Give the address space back to the process.
525 uintptr_t base = reinterpret_cast<uintptr_t>(m_pTlsBase);
527 m_pParent->freeUserRange(Process::UserRegion::Dynamic, base, THREAD_TLS_SIZE);
528 else
529 m_pParent->freeUserRange(Process::UserRegion::Normal, base, THREAD_TLS_SIZE);
530 } else if (m_pTlsBase && !m_bTlsBaseOverride) {
531 ERROR("Thread: no parent, but a TLS base exists.");
532 }
533
534 // Remove us from the scheduler.
536
537 EMIT_IF(X86_COMMON) {
538 // Make sure the floating-point fault handler doesn't care about us anymore
539 NMFaultHandler::instance().threadTerminated(this);
540 }
541
542 if (m_pParent)
543 m_pParent->removeThread(this);
544 Metrics::increment(Metrics::ThreadDestroyed);
545}
546
548 // The final process owner calls this before mapping teardown. Its later
549 // shutdown may hold the Process lock, where repeating blocking hooks is unsafe.
550 if (__atomic_exchange_n(&m_bSubsystemExitNotified, true, __ATOMIC_ACQ_REL)) {
551 return;
552 }
553 if (m_pParent) {
555 }
556 // Robust-list and clear-TID work above still needs the departing user stack.
557 // Retire owned raw stacks here, before a later scheduler-locked destruction.
558 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
559 VirtualAddressSpace::Stack* stack = m_StateLevels[level].m_pUserStack;
560 if (!stack || !stack->regionId() || !m_pParent)
561 continue;
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;
565 }
567 }
568}
569
571 {
572 auto senderGuard = m_EventSenderDrainWaiters.acquire();
574 if (m_bShutdown) {
575 return;
576 }
577 m_bShutdown = true;
578 Metrics::increment(Metrics::ThreadExitStarted);
579 }
580
581 // Admission and this predicate share one WaitQueue guard. A sender which
582 // passed the shutdown check therefore either releases its pin before this
583 // check or publishes a wake after this waiter is visible.
584 while (true) {
585 auto senderGuard = m_EventSenderDrainWaiters.acquire();
586 {
589 break;
590 }
591 }
592
593 const WaitQueue::WakeReason reason = senderGuard.waitForCompletion(
594 WaitQueue::Channel(this), Thread::EventWait, reinterpret_cast<uintptr_t>(this));
595 (void)reason;
596 }
597
599
600 if (m_pParent) {
602 }
603
604 // Once shutdown is visible, no sender can publish another event. Remove
605 // each queued registration under the thread lock, but complete it outside
606 // the lock because completion can wake waiters or destroy the Event.
607 while (true) {
608 Event* event = nullptr;
609 {
611 if (!m_EventQueue.count()) {
612 break;
613 }
614 event = m_EventQueue.popFront();
615 }
616
617 event->completeDelivery(this);
618 }
619
620 // Subsystem teardown must happen while the Process and address space are
621 // still live, and before a joiner can observe this exit.
623
624 // Make a joiner runnable before the scheduler chooses our replacement.
625 // This matters during shutdown after the idle thread has been retired.
626 // join() still checks m_bReapable and cannot delete us until the scheduler
627 // has switched off this stack.
628 {
629 auto guard = m_JoinWaiters.acquire();
630 m_bExitStarted = true;
631 guard.wakeAll();
632 }
633
634 // This is only an exit-announced scheduler state. Join completion is
635 // deliberately delayed until markReapable(). The status transition must
636 // also withdraw any ready-queue publication before the thread is retired.
637 setStatus(Thread::AwaitingJoin);
638}
639
641 // A discard callback can release the final reference to the object which
642 // owns a WaitQueue. Unpublish every intrusive waiter before invoking any
643 // such callback.
644 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
645 WaitQueue::Waiter& waiter = m_StateLevels[level].m_Waiter;
646 WaitQueue* queue = waiter.loadQueue();
647 if (queue) {
648 queue->cancel(&waiter, WaitQueue::WakeReason::Terminating);
649 }
650 }
651}
652
653void Thread::setClearChildTid(uintptr_t address) {
655 if (m_bShutdown) {
656 // A delayed clone selected for termination before registration never
657 // reaches userspace, so do not publish a pointer after its one-shot
658 // subsystem exit hook has begun.
659 return;
660 }
661 __atomic_store_n(&m_ClearChildTid, address, __ATOMIC_RELEASE);
662}
663
664void Thread::setRobustList(uintptr_t address, size_t ownerId) {
666 if (!m_bShutdown) {
667 m_RobustListOwnerId = ownerId;
668 __atomic_store_n(&m_RobustList, address, __ATOMIC_RELEASE);
669 }
670}
671
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);
677}
678
679void Thread::forceToStartupProcessor() {
680 PerProcessorScheduler* destination = Scheduler::instance().getBootstrapProcessorScheduler();
681 if (getScheduler() == destination) {
682 return;
683 }
684
685 if (Processor::information().getCurrentThread() != this) {
686 ERROR(
687 "Thread::forceToStartupProcessor must be run as the desired "
688 "thread.");
689 return;
690 }
691
692 const bool interrupts = Processor::getInterrupts();
693 TerminationDeferral lifetime;
694 bool migratable;
695 {
697 migratable = m_Placement.migratable;
698 m_Placement.migratable = true;
699 }
700 CpuAffinityMask startup;
701 startup.set(destination->logicalCpu());
702 while (true) {
703 uint64_t generation = 0;
704 const auto result = requestAffinity(startup, generation);
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)
710 break;
711 }
712 if (completeAffinityAtSafePoint() != AffinityResult::Success)
713 FATAL("Startup processor migration was terminated at its safe point.");
714 Processor::setInterrupts(interrupts);
716 m_Placement.migratable = migratable;
717}
718
721 setStatusUnlocked(s);
722}
723
724void Thread::setStatusUnlocked(Thread::Status s) {
725 if (m_Status == Thread::Zombie) {
726 if (s != Thread::Zombie) {
727 WARNING("Error condition in Thread::setStatus, more info below...");
728 WARNING("Parent process ID: " << m_pParent->getId());
729 FATAL(
730 "Thread::setStatus called with non-zombie status, when the "
731 "thread is a zombie!");
732 }
733
734 return;
735 }
736
737 if (s == Thread::Zombie) {
738 // shutdown owns event cleanup outside m_Lock; deleteThread publishes
739 // terminal retirement only after the stack handoff.
740 FATAL("Thread zombie transition must use off-stack retirement.");
741 }
742
743 m_Status = s;
744
745 PerProcessorScheduler* scheduler = getScheduler();
746 if (scheduler) {
748 }
749}
750
752 {
754 if (m_Status != Thread::Created || getUnwindState() == Thread::TerminateThread ||
756 return false;
757 }
758
759 m_bStartRequested = true;
760 }
761
762 // The add worker parks while holding m_Lock, then observes this
763 // out-of-lock publication. This ordering makes start the wake predicate
764 // without allowing the worker to preempt us under the thread lock.
765 Scheduler::instance().threadStatusChanged(this);
766 return true;
767}
768
770 Process* parent = m_pParent;
771 if (!parent->beginThreadJoin()) {
772 return false;
773 }
774
775 bool claimed = false;
776 bool processExitOwned = false;
777 {
778 RecursingLockGuard<Spinlock> processGuard(parent->m_Lock);
779 auto guard = m_JoinWaiters.acquire();
781 m_bDetached = true;
783 processExitOwned = m_bProcessExitOwned;
784 claimed = true;
785 }
786 }
787
788 if (!claimed) {
789 parent->endThreadJoin();
790 return false;
791 }
792
793 if (processExitOwned) {
795 }
796 const bool started = start();
797 const bool accepted = started || processExitOwned || getUnwindState() == Thread::TerminateThread;
798 if (!accepted) {
800 }
801
802 bool deleteNow = false;
803 {
804 RecursingLockGuard<Spinlock> processGuard(parent->m_Lock);
805 auto guard = m_JoinWaiters.acquire();
806 deleteNow = m_bReapable && !m_bProcessExitOwned;
807 if (!deleteNow) {
809 }
810 }
811
812 if (deleteNow) {
814 {
815 RecursingLockGuard<Spinlock> processGuard(parent->m_Lock);
816 {
817 auto guard = m_JoinWaiters.acquire();
818 deleteNow =
820 }
821 }
822 if (deleteNow) {
823 requireThreadDestructionContext();
824 delete this;
825 }
826 }
827
828 parent->endThreadJoin();
829 return accepted;
830}
831
832SchedulerState& Thread::state() {
833 return *(m_StateLevels[m_nStateLevel].m_State);
834}
835
836ExecutionContext Thread::executionContext() const {
837 const size_t level = __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
838 return m_StateLevels[level].m_ExecutionContext.current();
839}
840
841SchedulerState* Thread::pushState() {
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!");
845 return nullptr;
846 }
847 const size_t nextLevel = previousLevel + 1;
848
849#if HOSTED
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");
853 }
854#endif
855
856 if (__atomic_load_n(&m_pDeferredScopes[nextLevel], __ATOMIC_ACQUIRE)) {
857 FATAL("Thread state level reused with an armed cleanup record.");
858 }
859
860 // Prepare the unused level before publishing it to remote event senders.
861 // Stack allocation and replacing an old SharedPointer can free memory, so
862 // neither belongs in the short publication critical section below.
863 allocateStackAtLevel(nextLevel);
864 m_StateLevels[nextLevel].m_InhibitMask = m_StateLevels[previousLevel].m_InhibitMask;
865#if X64
866 // State levels are reused. A new handler must not inherit an FPU image
867 // left behind by an earlier handler at the same nesting depth.
868 m_StateLevels[nextLevel].m_State->flags &= ~(1U << 1);
869#endif
870 m_StateLevels[nextLevel].m_InterruptionReason = NotInterrupted;
871 m_StateLevels[nextLevel].m_bDispatchingWaitEvent = false;
872 m_StateLevels[nextLevel].m_SavedSignalMask = 0;
873 m_StateLevels[nextLevel].m_TemporarySignalMaskActive = false;
874 m_StateLevels[nextLevel].m_TemporarySignalWaitInterrupted = false;
875 m_StateLevels[nextLevel].m_DeferredSignalMaskRestore = false;
876 m_StateLevels[nextLevel].m_DispatchedSignalNumber = 0;
877 m_StateLevels[nextLevel].m_DispatchedSignalContinuationEpoch = 0;
878 m_StateLevels[nextLevel].m_bOwnsAlternateSignalStack = false;
879 m_StateLevels[nextLevel].m_ExecutionContext = m_StateLevels[previousLevel].m_ExecutionContext;
880 m_StateLevels[nextLevel].m_pRequestQueueCallback =
881 m_StateLevels[previousLevel].m_pRequestQueueCallback;
882
883#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
884 observeStateTransition(StatePushBeforePublish, this, previousLevel, nextLevel);
885#endif
886
887 SchedulerState* previousState = m_StateLevels[previousLevel].m_State;
888 const bool interruptsWereEnabled = Processor::getInterrupts();
890 {
892 if (m_nStateLevel != previousLevel) {
893 FATAL("Thread state level changed during push publication.");
894 }
895
896 // Refresh mutable per-level scalars while serialised with their public
897 // accessors, then release-publish the completely prepared level.
898 m_StateLevels[nextLevel].m_SignalMask = m_StateLevels[previousLevel].m_SignalMask;
899 m_StateLevels[nextLevel].m_Errno = m_StateLevels[previousLevel].m_Errno;
900 __atomic_store_n(&m_nStateLevel, nextLevel, __ATOMIC_RELEASE);
901 }
902
903#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
904 observeStateTransition(StatePushAfterPublish, this, previousLevel, nextLevel);
905#endif
906
908 Processor::setInterrupts(interruptsWereEnabled);
909
910 return previousState;
911}
912
913void Thread::popState(bool clean) {
914 const bool interruptsWereEnabled = Processor::getInterrupts();
916
917 const size_t origStateLevel = __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
918
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)");
922 Processor::setInterrupts(interruptsWereEnabled);
923 return;
924 }
925
926 if (__atomic_load_n(&m_pDeferredScopes[origStateLevel], __ATOMIC_ACQUIRE)) {
927 FATAL("Normal state pop attempted with armed cleanup records.");
928 }
929
930 const size_t nextLevel = origStateLevel - 1;
931 {
933 if (m_nStateLevel != origStateLevel) {
934 FATAL("Thread state level changed during pop publication.");
935 }
936 if (m_StateLevels[origStateLevel].m_bOwnsAlternateSignalStack) {
937 m_AlternateSignalStack.inUse = false;
938 m_StateLevels[origStateLevel].m_bOwnsAlternateSignalStack = false;
939 }
940 __atomic_store_n(&m_nStateLevel, nextLevel, __ATOMIC_RELEASE);
941 }
942
943#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
944 observeStateTransition(StatePopAfterPublish, this, origStateLevel, nextLevel);
945#endif
946
948
949 if (clean) {
950 cleanStateLevel(origStateLevel);
951 }
952
953 Processor::setInterrupts(interruptsWereEnabled);
954}
955
957 const size_t level = __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
958 if (!level) {
959 FATAL("Cannot abandon the base Thread state.");
960 }
961 retireDeferredScopes(false, level);
962 popState(clean);
963}
964
966 while (getStateLevel()) {
967 // The caller is still running on the outermost physical stack until
968 // its no-return transition, so every logical pop preserves storage.
969 abandonCurrentState(false);
970 }
971}
972
973VirtualAddressSpace::Stack* Thread::getStateUserStack() {
974 return m_StateLevels[m_nStateLevel].m_pUserStack;
975}
976
977void Thread::setStateUserStack(VirtualAddressSpace::Stack* st) {
978 m_StateLevels[m_nStateLevel].m_pUserStack = st;
979}
980
982 if (Processor::information().getCurrentThread() != this) {
983 FATAL("Exec attempted to discard another Thread's user stacks.");
984 }
985
986 VirtualAddressSpace::Stack* discarded[MAX_NESTED_EVENTS] = {};
987 size_t discardedCount = 0;
988 {
990 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
991 VirtualAddressSpace::Stack* stack = m_StateLevels[level].m_pUserStack;
992 m_StateLevels[level].m_pUserStack = nullptr;
993 if (!stack) {
994 continue;
995 }
996
997 bool alreadyDiscarded = false;
998 for (size_t i = 0; i < discardedCount; ++i) {
999 if (discarded[i] == stack) {
1000 alreadyDiscarded = true;
1001 break;
1002 }
1003 }
1004 if (!alreadyDiscarded) {
1005 discarded[discardedCount++] = stack;
1006 }
1007 }
1008 }
1009
1010 // revertToKernelAddressSpace has already retired the mappings. Calling
1011 // freeStack here could unmap the replacement image if it reuses an old
1012 // stack address; only the descriptor itself remains ours to release.
1013 for (size_t i = 0; i < discardedCount; ++i) {
1014 delete discarded[i];
1015 }
1016}
1017
1019 if (!stack) {
1020 FATAL("Cannot adopt an empty exec user stack.");
1021 }
1022
1024 if (m_StateLevels[0].m_pUserStack) {
1025 FATAL("Exec attempted to replace an owned base user stack.");
1026 }
1027 m_StateLevels[0].m_pUserStack = stack;
1028}
1029
1031 Thread* thread = Processor::information().getCurrentThread();
1032 if (!thread) {
1033 FATAL("Kernel thread root returned without a current Thread.");
1034 }
1035 if (thread->getStateLevel()) {
1036 FATAL("Kernel thread root returned with nested event state still active.");
1037 }
1038
1039 const UnwindType unwindState = thread->getUnwindState();
1040 if (unwindState == Exit) {
1041 Process* process = thread->getParent();
1042 Subsystem* subsystem = process ? process->getSubsystem() : nullptr;
1043 if (!subsystem) {
1044 FATAL("Kernel thread root reached process exit without a subsystem.");
1045 }
1046 const DeferredProcessExit request = thread->takeDeferredProcessExit();
1047 subsystem->exit(request.code, request.cause);
1048 FATAL("Subsystem::exit returned to a kernel thread root.");
1049 }
1050
1051 Processor::information().getScheduler().commitCurrentThreadExit();
1052}
1053
1054void Thread::allocateStackAtLevel(size_t stateLevel) {
1055 if (stateLevel >= MAX_NESTED_EVENTS)
1056 stateLevel = MAX_NESTED_EVENTS - 1;
1057 if (m_StateLevels[stateLevel].m_pKernelStack == 0)
1058 m_StateLevels[stateLevel].m_pKernelStack =
1060#if HOSTED
1061 VirtualAddressSpace::Stack* stack = m_StateLevels[stateLevel].m_pKernelStack;
1062 if (stack) {
1063 SchedulerState* state = m_StateLevels[stateLevel].m_State;
1064 state->stackBase = reinterpret_cast<uintptr_t>(stack->getBase());
1065 state->stackSize = stack->getSize();
1066 }
1067#endif
1068}
1069
1071 if (m_nStateLevel >= MAX_NESTED_EVENTS)
1072 FATAL("m_nStateLevel > MAX_NESTED_EVENTS: " << m_nStateLevel << "...");
1073 if (m_StateLevels[m_nStateLevel].m_pKernelStack != 0) {
1074 return m_StateLevels[m_nStateLevel].m_pKernelStack->getTop();
1075 } else {
1076 return 0;
1077 }
1078}
1079
1080void* Thread::getKernelStackBase(size_t* size) const {
1081 if (m_nStateLevel >= MAX_NESTED_EVENTS)
1082 FATAL("m_nStateLevel > MAX_NESTED_EVENTS: " << m_nStateLevel << "...");
1084#if HOSTED
1085 if (!stack) {
1086 stack = m_StateLevels[m_nStateLevel].m_pAuxillaryStack;
1087 }
1088#endif
1089 if (stack) {
1090 *size = stack->getSize();
1091 return stack->getBase();
1092 } else {
1093 ERROR("No kernel stack at this level!");
1094 *size = 0;
1095 return 0;
1096 }
1097}
1098
1100 uintptr_t stack = 0;
1101 if (m_StateLevels[m_nStateLevel].m_pKernelStack) {
1102 stack = reinterpret_cast<uintptr_t>(m_StateLevels[m_nStateLevel].m_pKernelStack->getTop());
1103 }
1104 Processor::information().setKernelStack(stack);
1105}
1106
1107void Thread::pokeState(size_t stateLevel, SchedulerState& state) {
1108 if (stateLevel >= MAX_NESTED_EVENTS) {
1109 ERROR("Thread::pokeState(): stateLevel `" << stateLevel << "' is over the maximum.");
1110 return;
1111 }
1112 *(m_StateLevels[stateLevel].m_State) = state;
1113}
1114
1116 Event::SendLease eventSendLease = pEvent->beginSend();
1117 if (!eventSendLease) {
1118 return false;
1119 }
1120
1121 bool accepted = false;
1122 {
1123 auto senderGuard = m_EventSenderDrainWaiters.acquire();
1124 {
1126 if (m_bShutdown || m_Status == Zombie) {
1127 return false;
1128 }
1130 }
1131 }
1132
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);
1138 }
1139#endif
1140
1141 // Event registration can allocate. The in-flight pin lets this happen
1142 // outside m_Lock without opening a registration-vs-destruction gap.
1143 const bool eventRegistered = pEvent->registerThread(this);
1144
1145 bool duplicate = false;
1146 bool wakeThread = false;
1147 PerProcessorScheduler* readyScheduler = nullptr;
1148 if (eventRegistered) {
1149 // Serialise queue inspection in waitForEvent() with event publication.
1150 auto eventWaitGuard = m_EventWaiters.acquire();
1151 {
1153 if (!m_bShutdown && m_Status != Zombie) {
1154 if (pEvent->isSignalEvent() && !static_cast<SignalEvent*>(pEvent)->queuedIndividually()) {
1155 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
1156 if ((*it)->isSignalEvent() && (*it)->getNumber() == pEvent->getNumber() &&
1157 static_cast<SignalEvent*>(*it)->isProcessDirected() ==
1158 static_cast<SignalEvent*>(pEvent)->isProcessDirected()) {
1159 duplicate = true;
1160 break;
1161 }
1162 }
1163 }
1164
1165 if (!duplicate) {
1166 m_EventQueue.pushBack(pEvent);
1167 markUserReturnWorkPending();
1168 wakeThread = hasDeliverableEventsUnlocked() &&
1169 interruptWaitUnlocked(WaitQueue::WakeReason::Event, readyScheduler);
1170 }
1171 accepted = true;
1172 }
1173 }
1174 }
1175
1176 if (!eventRegistered) {
1177 accepted = false;
1178 } else if (!accepted) {
1179 pEvent->deregisterThread(this);
1180 } else if (duplicate) {
1181 pEvent->completeDelivery(this);
1182 } else if (wakeThread) {
1183 assert(readyScheduler);
1184 readyScheduler->publishReadyFromWait(this);
1185 }
1186
1187 {
1188 auto senderGuard = m_EventSenderDrainWaiters.acquire();
1189 bool drained = false;
1190 {
1192 assert(m_EventSendersInFlight);
1193 drained = !--m_EventSendersInFlight;
1194 }
1195 if (drained) {
1196 senderGuard.wakeAll(WaitQueue::WakeReason::Signalled, WaitQueue::Channel(this));
1197 }
1198 }
1199 return accepted;
1200}
1201
1202void Thread::waitForEvent(WaitQueue::StackDiscardCleanup onStackDiscard,
1203 void* stackDiscardContext) {
1204 waitForEventInternal(false, onStackDiscard, stackDiscardContext);
1205}
1206
1207bool Thread::waitForEventOrSignalInterruption(WaitQueue::StackDiscardCleanup onStackDiscard,
1208 void* stackDiscardContext) {
1209 return waitForEventInternal(true, onStackDiscard, stackDiscardContext);
1210}
1211
1212bool Thread::waitForEventInternal(bool stopOnSignalInterruption,
1213 WaitQueue::StackDiscardCleanup onStackDiscard,
1214 void* stackDiscardContext) {
1215 StackDiscardScope discardScope(onStackDiscard, stackDiscardContext);
1216 while (true) {
1217 if (getUnwindState() != Continue) {
1218 return false;
1219 }
1220
1221 bool ready = false;
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) {
1230 hook(this);
1231 }
1232 }
1233#endif
1234 {
1235 auto guard = m_EventWaiters.acquire();
1236
1237 m_Lock.acquire();
1238 ready = hasDeliverableEventsUnlocked();
1239 if (stopOnSignalInterruption) {
1240 const StateLevel& state = m_StateLevels[m_nStateLevel];
1241 signalInterrupted = state.m_TemporarySignalMaskActive &&
1242 state.m_TemporarySignalWaitInterrupted &&
1243 state.m_InterruptionReason == InterruptedBySignal;
1244 }
1245 m_Lock.release();
1246 if (!ready && !signalInterrupted) {
1247 reason = guard.wait(WaitQueue::Channel(), Thread::EventWait,
1248 reinterpret_cast<uintptr_t>(__builtin_return_address(0)));
1249 }
1250 }
1251
1252 if (signalInterrupted) {
1253 return true;
1254 }
1255
1256 if (ready && getUnwindState() == Continue) {
1257 // A pre-existing event did not pass through WaitQueue::wait(), so
1258 // dispatch it explicitly after dropping the event-wait guard and
1259 // identify it as the event which satisfied this wait.
1260 const size_t stateLevel = getStateLevel();
1261 m_StateLevels[stateLevel].m_bDispatchingWaitEvent = true;
1262 Processor::information().getScheduler().checkEventState(0);
1263 m_StateLevels[stateLevel].m_bDispatchingWaitEvent = false;
1264 return stopOnSignalInterruption && hasTemporarySignalWaitInterruption();
1265 }
1266
1267 if (reason == WaitQueue::WakeReason::Event || reason == WaitQueue::WakeReason::Terminating ||
1268 reason == WaitQueue::WakeReason::Unwinding) {
1269 return stopOnSignalInterruption && hasTemporarySignalWaitInterruption();
1270 }
1271 }
1272}
1273
1274#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1275namespace {
1276Atomic<size_t> g_HostedPrequeuedEventCalls(0);
1277Atomic<size_t> g_HostedShutdownEventCalls(0);
1278Atomic<size_t> g_HostedShutdownEventDestructions(0);
1279Atomic<size_t> g_HostedShutdownThreadCalls(0);
1280Atomic<size_t> g_HostedSelfRetireCalls(0);
1281Atomic<size_t> g_HostedSelfRetireDestructions(0);
1282Atomic<size_t> g_HostedAdmissionRetireDestructions(0);
1283Event* g_pHostedSelfRetireEvent = nullptr;
1284
1285struct HostedAdmissionRetireContext {
1286 HostedAdmissionRetireContext(Event* event, size_t destructionsBefore)
1287 : event(event), destructionsBefore(destructionsBefore), calls(0), destroyedInsideHook(0) {}
1288
1289 Event* event;
1290 size_t destructionsBefore;
1291 Atomic<size_t> calls;
1292 Atomic<size_t> destroyedInsideHook;
1293};
1294
1295HostedAdmissionRetireContext* g_pHostedAdmissionRetireContext = nullptr;
1296
1297void hostedPrequeuedEventHandler(size_t) {
1298 g_HostedPrequeuedEventCalls += 1;
1299}
1300
1301void hostedShutdownEventHandler(size_t) {
1302 g_HostedShutdownEventCalls += 1;
1303}
1304
1305void hostedSelfRetireEventHandler(size_t) {
1306 Event* event = g_pHostedSelfRetireEvent;
1307 g_pHostedSelfRetireEvent = nullptr;
1308 if (event) {
1309 event->retire();
1310 g_HostedSelfRetireCalls += 1;
1311 }
1312}
1313
1314void hostedAdmissionRetireHook(Thread*) {
1315 HostedAdmissionRetireContext* context = g_pHostedAdmissionRetireContext;
1316 if (!context) {
1317 return;
1318 }
1319
1320 context->calls += 1;
1321 context->event->retire();
1322 if (g_HostedAdmissionRetireDestructions != context->destructionsBefore) {
1323 context->destroyedInsideHook += 1;
1324 }
1325}
1326
1327class HostedPrequeuedEvent : public Event {
1328 public:
1329 HostedPrequeuedEvent()
1330 : Event(reinterpret_cast<uintptr_t>(&hostedPrequeuedEventHandler), false) {}
1331
1332 size_t serialize(uint8_t*) override {
1333 return 0;
1334 }
1335
1336 size_t getNumber() override {
1337 return 0x57414954;
1338 }
1339};
1340
1341class HostedShutdownStableEvent : public Event {
1342 public:
1343 HostedShutdownStableEvent()
1344 : Event(reinterpret_cast<uintptr_t>(&hostedShutdownEventHandler), false) {}
1345
1346 size_t serialize(uint8_t*) override {
1347 return 0;
1348 }
1349
1350 size_t getNumber() override {
1351 return 0x53484453;
1352 }
1353};
1354
1355class HostedShutdownDeletableEvent : public Event {
1356 public:
1357 HostedShutdownDeletableEvent()
1358 : Event(reinterpret_cast<uintptr_t>(&hostedShutdownEventHandler), true) {}
1359
1360 ~HostedShutdownDeletableEvent() override {
1361 g_HostedShutdownEventDestructions += 1;
1362 }
1363
1364 size_t serialize(uint8_t*) override {
1365 return 0;
1366 }
1367
1368 size_t getNumber() override {
1369 return 0x53484444;
1370 }
1371};
1372
1373class HostedSelfRetireEvent : public Event {
1374 public:
1375 HostedSelfRetireEvent()
1376 : Event(reinterpret_cast<uintptr_t>(&hostedSelfRetireEventHandler), false) {}
1377
1378 ~HostedSelfRetireEvent() override {
1379 g_HostedSelfRetireDestructions += 1;
1380 }
1381
1382 size_t serialize(uint8_t*) override {
1383 return 0;
1384 }
1385
1386 size_t getNumber() override {
1387 return 0x53455254;
1388 }
1389};
1390
1391class HostedAdmissionRetireEvent : public Event {
1392 public:
1393 HostedAdmissionRetireEvent()
1394 : Event(reinterpret_cast<uintptr_t>(&hostedShutdownEventHandler), false) {}
1395
1396 ~HostedAdmissionRetireEvent() override {
1397 g_HostedAdmissionRetireDestructions += 1;
1398 }
1399
1400 size_t serialize(uint8_t*) override {
1401 return 0;
1402 }
1403
1404 size_t getNumber() override {
1405 return 0x41525254;
1406 }
1407};
1408
1409int hostedShutdownThread(void*) {
1410 g_HostedShutdownThreadCalls += 1;
1411 return 0;
1412}
1413
1414struct HostedStatePublicationContext {
1415 HostedStatePublicationContext(Thread* thread, Event* event)
1416 : thread(thread), event(event), calls(0), failures(0) {}
1417
1418 Thread* thread;
1419 Event* event;
1420 Atomic<size_t> calls;
1421 Atomic<size_t> failures;
1422};
1423
1424HostedStatePublicationContext* g_StatePublicationContext = nullptr;
1425
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);
1430 if (!context) {
1431 return;
1432 }
1433
1434 context->calls += 1;
1435 const size_t expectedVisibleLevel =
1436 window == Thread::StatePushBeforePublish ? previousLevel : nextLevel;
1437 if (thread != context->thread || thread->getStateLevel() != expectedVisibleLevel ||
1438 (window != Thread::StatePushBeforePublish && Processor::getInterrupts()) ||
1439 !thread->sendEvent(context->event)) {
1440 context->failures += 1;
1441 }
1442}
1443
1444struct HostedDeliveryLeaseContext {
1445 explicit HostedDeliveryLeaseContext(Event* event) : event(event), entered(0), completed(0) {}
1446
1447 Event* event;
1448 Atomic<size_t> entered;
1449 Atomic<size_t> completed;
1450};
1451
1452int hostedDeliveryLeaseWaiter(void* parameter) {
1453 HostedDeliveryLeaseContext* context = reinterpret_cast<HostedDeliveryLeaseContext*>(parameter);
1454 context->entered += 1;
1455 context->event->waitForDeliveries();
1456 context->completed += 1;
1457 return 0;
1458}
1459} // namespace
1460
1461void Thread::setStateTransitionHook(StateTransitionHook hook) {
1462 __atomic_store_n(&g_StateTransitionHook, hook, __ATOMIC_RELEASE);
1463}
1464
1465void Thread::setJoinOperationHook(JoinOperationHook hook) {
1466 __atomic_store_n(&g_JoinOperationHook, hook, __ATOMIC_RELEASE);
1467}
1468
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);
1473}
1474
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);
1479}
1480
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);
1484}
1485
1486bool Thread::isReapableForHostedTest() {
1487 auto guard = m_JoinWaiters.acquire();
1488 return m_bReapable;
1489}
1490
1491bool Thread::wasStartPublishedForHostedTest() {
1493 return m_bStartRequested || m_Status == Ready || m_Status == Running;
1494}
1495
1496bool Thread::waitUntilReapableForHostedTest() {
1497 TerminationDeferral terminationDeferral;
1498 while (true) {
1499 auto guard = m_JoinWaiters.acquire();
1500 if (m_bReapable) {
1501 return true;
1502 }
1503
1504 const WaitQueue::WakeReason reason = guard.waitForCompletion(
1505 WaitQueue::Channel(), Thread::Joining, reinterpret_cast<uintptr_t>(this));
1506 (void)reason;
1507 }
1508}
1509
1510bool Thread::runHostedPrequeuedEventRegression() {
1511 if (Processor::information().getCurrentThread() != this) {
1512 return false;
1513 }
1514
1515 constexpr size_t Iterations = 16;
1516 HostedPrequeuedEvent event;
1517 const size_t initialStateLevel = getStateLevel();
1518 const size_t callsBefore = g_HostedPrequeuedEventCalls;
1519 for (size_t iteration = 0; iteration < Iterations; ++iteration) {
1520 if (!sendEvent(&event) || event.pendingCount() != 1 || !hasEvent(&event)) {
1521 return false;
1522 }
1523
1524 waitForEvent();
1525
1526 if (g_HostedPrequeuedEventCalls != (callsBefore + iteration + 1) || event.pendingCount() != 0 ||
1527 hasEvent(&event) || getStateLevel() != initialStateLevel) {
1528 return false;
1529 }
1530 }
1531
1532 return true;
1533}
1534
1535bool Thread::runHostedStatePublicationRegression() {
1536 if (Processor::information().getCurrentThread() != this ||
1537 (getStateLevel() + 1) >= MAX_NESTED_EVENTS) {
1538 return false;
1539 }
1540
1541 HostedPrequeuedEvent event;
1542 HostedStatePublicationContext context(this, &event);
1543 const size_t initialStateLevel = getStateLevel();
1544 __atomic_store_n(&g_StatePublicationContext, &context, __ATOMIC_RELEASE);
1545 setStateTransitionHook(hostedStatePublicationHook);
1546
1547 SchedulerState* previousState = pushState();
1548 const bool pushed = previousState && getStateLevel() == (initialStateLevel + 1);
1549 if (previousState) {
1550 popState();
1551 }
1552
1553 setStateTransitionHook(nullptr);
1554 __atomic_store_n(&g_StatePublicationContext, static_cast<HostedStatePublicationContext*>(nullptr),
1555 __ATOMIC_RELEASE);
1556
1557 const bool publishedSafely = pushed && getStateLevel() == initialStateLevel &&
1558 context.calls == 3 && context.failures == 0 &&
1559 event.pendingCount() == 3 && hasEvent(&event);
1560 cullEvent(&event);
1561 const bool deliveriesCulled = event.pendingCount() == 0 && !hasEvent(&event);
1562
1563 return publishedSafely && deliveriesCulled;
1564}
1565
1566bool Thread::runHostedStateCleanupRegression() {
1567 const size_t initialLevel = getStateLevel();
1568 if (!clearUserReturnWorkIfIdle() || userReturnWorkPending() || !canSkipUserReturnWork()) {
1569 return false;
1570 }
1571 const auto terminationWorkPending = [this]() {
1572 return isTerminationDeferred() && userReturnWorkPending() && !canSkipUserReturnWork() &&
1573 !clearUserReturnWorkIfIdle();
1574 };
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};
1582 DeferredScopeRecord oldRecord;
1583 DeferredScopeRecord firstRecord;
1584 AtomicStateCleanupRecord secondRecord;
1585 DeferredScopeRecord normalRecord;
1586 DeferredScopeRecord baseRecord;
1587 DeferredScopeRecord terminationRecord;
1588 DeferredScopeRecord checkpointTerminationRecord;
1589 DeferredScopeRecord levelTerminationRecord;
1590 AtomicStateCleanupRecord levelRecord;
1591
1592 armStateCleanup(oldRecord, hostedStateCleanupCallback, &oldItem);
1593 const size_t checkpoint = stateCleanupCheckpoint();
1594 armStateCleanup(firstRecord, hostedStateCleanupCallback, &firstItem);
1595 armAtomicStateCleanup(secondRecord, hostedStateCleanupCallback, &secondItem);
1596 const bool cleanupDoesNotDeferTermination = !isTerminationDeferred();
1597 registerFreshTerminationDeferral(checkpointTerminationRecord);
1598 retireDeferredScopesAfter(checkpoint);
1599
1600 const bool checkpointPassed = order.count == 2 && order.values[0] == 2 && order.values[1] == 1 &&
1601 oldRecord.armed && !firstRecord.armed && !secondRecord.armed &&
1602 !checkpointTerminationRecord.armed && !isTerminationDeferred() &&
1603 !userReturnWorkPending() && canSkipUserReturnWork();
1604 disarmStateCleanup(oldRecord);
1605
1606 armStateCleanup(normalRecord, hostedStateCleanupCallback, &normalItem);
1607 disarmStateCleanup(normalRecord);
1608 const bool normalPassed = order.count == 2 && !normalRecord.armed;
1609
1610 const uint64_t originalSignalMask = getSignalMask();
1611 const uint64_t temporarySignalMask = originalSignalMask ^ (static_cast<uint64_t>(1) << 7);
1612 const size_t temporaryMaskCheckpoint = stateCleanupCheckpoint();
1613 bool temporaryMaskActive = false;
1614 {
1615 TemporarySignalMask signalMask(*this, temporarySignalMask);
1616 temporaryMaskActive = getSignalMask() == temporarySignalMask;
1617 retireDeferredScopesAfter(temporaryMaskCheckpoint);
1618 }
1619 const bool temporaryMaskCleanupPassed = temporaryMaskActive &&
1620 getSignalMask() == originalSignalMask &&
1622
1623 const ExecutionContext originalContext = Processor::executionContext();
1624 const size_t contextCheckpoint = stateCleanupCheckpoint();
1625 bool contextCleanupPassed = true;
1626 {
1627 ExecutionContextGuard outer(ExecutionContext::HostedSyntheticIrq);
1628 {
1629 ExecutionContextGuard inner(ExecutionContext::DebuggerTrap);
1630 contextCleanupPassed &= Processor::executionContext() == ExecutionContext::DebuggerTrap;
1631 }
1632 contextCleanupPassed &= Processor::executionContext() == ExecutionContext::HostedSyntheticIrq;
1633 retireDeferredScopesAfter(contextCheckpoint);
1634 contextCleanupPassed &= Processor::executionContext() == originalContext;
1635 }
1636 contextCleanupPassed &= Processor::executionContext() == originalContext;
1637
1638 armStateCleanup(baseRecord, hostedStateCleanupCallback, &baseItem);
1639 const bool pushed = pushState() != nullptr;
1640 if (pushed) {
1641 armAtomicStateCleanup(levelRecord, hostedStateCleanupCallback, &levelItem);
1642 registerFreshTerminationDeferral(levelTerminationRecord);
1643 abandonCurrentState(false);
1644 }
1645 const bool levelPassed = pushed && getStateLevel() == initialLevel && order.count == 3 &&
1646 order.values[2] == 5 && baseRecord.armed && !levelRecord.armed &&
1647 !levelTerminationRecord.armed && !isTerminationDeferred() &&
1648 !userReturnWorkPending() && canSkipUserReturnWork();
1649 disarmStateCleanup(baseRecord);
1650
1651 registerDeferredScope(terminationRecord, true, false);
1652 const bool explicitTerminationDefers = terminationWorkPending();
1653 unregisterDeferredScope(terminationRecord);
1654 const bool explicitTerminationRetired = !isTerminationDeferred() && !terminationRecord.armed &&
1655 !userReturnWorkPending() && canSkipUserReturnWork();
1656
1657 bool pureScopesPassed = true;
1658 DeferredScopeRecord* initialHead =
1659 __atomic_load_n(&m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE);
1660 const size_t pureCheckpoint = stateCleanupCheckpoint();
1661 alignas(TerminationDeferral) uint8_t scopeStorage[sizeof(TerminationDeferral)];
1662 ByteSet(scopeStorage, 0xa5, sizeof(scopeStorage));
1663 TerminationDeferral* fresh = new (scopeStorage) TerminationDeferral();
1664 DeferredScopeRecord* freshRecord =
1665 __atomic_load_n(&m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE);
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();
1672 {
1673 TerminationDeferral moved(pedigree_std::move(*fresh));
1674 fresh->~TerminationDeferral();
1675 DeferredScopeRecord* movedRecord =
1676 __atomic_load_n(&m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE);
1677 pureScopesPassed &= movedRecord && movedRecord != freshRecord &&
1678 movedRecord->sequence == freshSequence && terminationWorkPending();
1679
1680 // Reuse poisoned storage so adoption cannot rely on an accidentally zero stack.
1681 ByteSet(scopeStorage, 0x5a, sizeof(scopeStorage));
1682 TerminationDeferral* disabled = new (scopeStorage) TerminationDeferral(false);
1683 pureScopesPassed &=
1684 __atomic_load_n(&m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE) == movedRecord;
1685 *disabled = pedigree_std::move(moved);
1686 DeferredScopeRecord* adoptedRecord =
1687 __atomic_load_n(&m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE);
1688 pureScopesPassed &=
1689 adoptedRecord && adoptedRecord->sequence == freshSequence && terminationWorkPending();
1690
1691 armStateCleanup(normalRecord, hostedStateCleanupCallback, &normalItem);
1692 {
1693 TerminationDeferral newer;
1694 *disabled = pedigree_std::move(newer);
1695 pureScopesPassed &=
1696 __atomic_load_n(&m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE) == &normalRecord &&
1697 normalRecord.next == adoptedRecord && adoptedRecord &&
1698 adoptedRecord->sequence == freshSequence && terminationWorkPending();
1699 }
1700 disarmStateCleanup(normalRecord);
1701 *disabled = TerminationDeferral(false);
1702 pureScopesPassed &=
1703 !isTerminationDeferred() && !userReturnWorkPending() && canSkipUserReturnWork() &&
1704 __atomic_load_n(&m_pDeferredScopes[initialLevel], __ATOMIC_ACQUIRE) == initialHead;
1705 disabled->~TerminationDeferral();
1706 }
1707
1708 bool nestedWorkPassed = true;
1709 DeferredScopeRecord eventOnlyRecord;
1710 {
1711 TerminationDeferral outer;
1712 nestedWorkPassed &= terminationWorkPending();
1713 registerDeferredScope(eventOnlyRecord, false, true);
1714 {
1715 TerminationDeferral inner;
1716 outer = TerminationDeferral(false);
1717 nestedWorkPassed &= terminationWorkPending();
1718 }
1719 nestedWorkPassed &= !isTerminationDeferred() && eventsDeferred() && userReturnWorkPending() &&
1720 !canSkipUserReturnWork() && !clearUserReturnWorkIfIdle();
1721 }
1722 unregisterDeferredScope(eventOnlyRecord);
1723 nestedWorkPassed &= !userReturnWorkPending() && canSkipUserReturnWork();
1724
1725 registerDeferredScope(eventOnlyRecord, true, true);
1726 nestedWorkPassed &= terminationWorkPending() && eventsDeferred();
1727 unregisterDeferredScope(eventOnlyRecord);
1728 nestedWorkPassed &= !isTerminationDeferred() && !eventsDeferred() && !userReturnWorkPending() &&
1729 canSkipUserReturnWork();
1730
1731 return cleanupDoesNotDeferTermination && checkpointPassed && normalPassed &&
1732 temporaryMaskCleanupPassed && contextCleanupPassed && levelPassed &&
1733 explicitTerminationDefers && explicitTerminationRetired && pureScopesPassed &&
1734 nestedWorkPassed && order.count == 3;
1735}
1736
1737bool Thread::runHostedExecStackOwnershipRegression() {
1738 if (Processor::information().getCurrentThread() != this || getStateLevel() != 0) {
1739 return false;
1740 }
1741
1742 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
1743 if (m_StateLevels[level].m_pUserStack) {
1744 return false;
1745 }
1746 }
1747
1748 constexpr size_t FakeStackSize = 4 * 4096;
1750 new VirtualAddressSpace::Stack(reinterpret_cast<void*>(0x100000), FakeStackSize);
1751 VirtualAddressSpace::Stack* oldNested =
1752 new VirtualAddressSpace::Stack(reinterpret_cast<void*>(0x200000), FakeStackSize);
1753 m_StateLevels[0].m_pUserStack = oldBase;
1754
1755 if (!pushState()) {
1756 m_StateLevels[0].m_pUserStack = nullptr;
1757 delete oldBase;
1758 delete oldNested;
1759 return false;
1760 }
1761
1762 const size_t nestedLevel = getStateLevel();
1763 m_StateLevels[nestedLevel].m_pUserStack = oldNested;
1764 // Exercise defensive duplicate handling in an otherwise unused level.
1765 m_StateLevels[MAX_NESTED_EVENTS - 1].m_pUserStack = oldBase;
1766
1768 bool allOldMetadataDiscarded = true;
1769 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
1770 allOldMetadataDiscarded &= m_StateLevels[level].m_pUserStack == nullptr;
1771 }
1772
1773 VirtualAddressSpace::Stack* replacement =
1774 new VirtualAddressSpace::Stack(reinterpret_cast<void*>(0x300000), FakeStackSize);
1775 adoptInitialUserStackForExec(replacement);
1776 const bool replacementOwnedByBase = m_StateLevels[0].m_pUserStack == replacement &&
1777 m_StateLevels[nestedLevel].m_pUserStack == nullptr;
1778
1779 // This regression uses synthetic descriptors with no mappings; detach the
1780 // replacement before ordinary state cleanup asks the address space to free it.
1781 m_StateLevels[0].m_pUserStack = nullptr;
1782 delete replacement;
1783 popState();
1784
1785 return allOldMetadataDiscarded && replacementOwnedByBase && getStateLevel() == 0;
1786}
1787
1788void Thread::withDeferredScopeLockForTest(DeferredScopeLockHook hook) {
1789 m_DeferredScopeRegressionLock.acquire();
1790 if (hook) {
1791 hook();
1792 }
1793 m_DeferredScopeRegressionLock.release();
1794}
1795
1796bool Thread::runHostedEventDeliveryLeaseRegression() {
1797 if (Processor::information().getCurrentThread() != this) {
1798 return false;
1799 }
1800
1801 HostedPrequeuedEvent event;
1802 if (!sendEvent(&event)) {
1803 return false;
1804 }
1805
1806 Event::Delivery delivery = getNextEvent();
1807 if (!delivery || delivery.get() != &event || hasEvent(&event) || event.pendingCount() != 1) {
1808 delivery.reset();
1809 cullEvent(&event);
1810 return false;
1811 }
1812
1813 HostedDeliveryLeaseContext context(&event);
1814 Thread* waiterA = new Thread(Scheduler::instance().getKernelProcess(), hostedDeliveryLeaseWaiter,
1815 &context, nullptr, false, true);
1816 waiterA->setName("hosted event-delivery lease waiter A");
1817
1818 while (context.entered != static_cast<size_t>(1)) {
1820 }
1821
1822 for (size_t i = 0; i < 4; ++i) {
1824 }
1825 Thread::WaitDebugInfo waiterInfo = {};
1826 const bool closePublished = waiterA->getWaitDebugInfo(waiterInfo) &&
1827 waiterInfo.channelOwner == &event && waiterInfo.queued;
1828 const bool rejectedAfterClose = closePublished && !sendEvent(&event);
1829 const bool leaseHeld = context.completed == 0 && event.pendingCount() == 1;
1830
1831 delivery.reset();
1832 while (context.completed != static_cast<size_t>(1)) {
1834 }
1835
1836 const bool waiterAJoined = waiterA->join();
1837 const bool deliveryLeasePassed = closePublished && rejectedAfterClose && leaseHeld &&
1838 waiterAJoined && event.pendingCount() == 0;
1839
1840 HostedPrequeuedEvent deferredEvent;
1841 const size_t callsBefore = g_HostedPrequeuedEventCalls;
1842 bool nestedDeferralPassed = false;
1843 {
1844 Uninterruptible outer;
1845 {
1846 Uninterruptible inner;
1847 if (!sendEvent(&deferredEvent)) {
1848 return false;
1849 }
1850 Processor::information().getScheduler().checkEventState(0);
1851 nestedDeferralPassed = g_HostedPrequeuedEventCalls == callsBefore &&
1852 hasEvent(&deferredEvent) && deferredEvent.pendingCount() == 1;
1853 }
1854
1855 Processor::information().getScheduler().checkEventState(0);
1856 nestedDeferralPassed = nestedDeferralPassed && g_HostedPrequeuedEventCalls == callsBefore &&
1857 hasEvent(&deferredEvent) && deferredEvent.pendingCount() == 1;
1858 }
1859
1860 Processor::information().getScheduler().checkEventState(0);
1861 nestedDeferralPassed = nestedDeferralPassed && g_HostedPrequeuedEventCalls == (callsBefore + 1) &&
1862 !hasEvent(&deferredEvent) && deferredEvent.pendingCount() == 0;
1863
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);
1869 if (retireQueued) {
1870 waitForEvent();
1871 } else {
1872 g_pHostedSelfRetireEvent = nullptr;
1873 delete retiringEvent;
1874 }
1875 const bool selfRetirePassed = retireQueued && !g_pHostedSelfRetireEvent &&
1876 g_HostedSelfRetireCalls == (retireCallsBefore + 1) &&
1877 g_HostedSelfRetireDestructions == (retireDestructionsBefore + 1);
1878
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),
1887 __ATOMIC_RELEASE);
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);
1894
1895 return deliveryLeasePassed && nestedDeferralPassed && selfRetirePassed && admissionRetirePassed;
1896}
1897
1898bool Thread::runHostedEventShutdownRegression() {
1899 if (Processor::information().getCurrentThread() != this) {
1900 return false;
1901 }
1902
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;
1909
1910 Thread* target = new Thread(Scheduler::instance().getKernelProcess(), hostedShutdownThread,
1911 nullptr, nullptr, false, true, true);
1912 target->setName("hosted event-queue shutdown regression");
1913
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;
1919 }
1920
1921 __atomic_store_n(&g_EventAdmissionTarget, target, __ATOMIC_RELEASE);
1922 __atomic_store_n(
1923 &g_EventAdmissionHook,
1924 +[](Thread* admissionTarget) {
1925 admissionTarget->setUnwindState(Thread::TerminateThread);
1926 while (true) {
1927 {
1928 LockGuard<Spinlock> guard(admissionTarget->m_Lock);
1929 if (admissionTarget->m_bShutdown) {
1930 break;
1931 }
1932 }
1934 }
1935 },
1936 __ATOMIC_RELEASE);
1937 const bool rejectedDuringShutdown = !target->sendEvent(&racingEvent);
1938 __atomic_store_n(&g_EventAdmissionHook, static_cast<EventAdmissionHook>(nullptr),
1939 __ATOMIC_RELEASE);
1940 __atomic_store_n(&g_EventAdmissionTarget, static_cast<Thread*>(nullptr), __ATOMIC_RELEASE);
1941
1942 bool shutdownObserved = false;
1943 constexpr size_t ShutdownAttempts = 10000;
1944 for (size_t attempt = 0; attempt < ShutdownAttempts; ++attempt) {
1945 {
1946 LockGuard<Spinlock> guard(target->m_Lock);
1947 shutdownObserved = target->m_bShutdown;
1948 }
1949 if (shutdownObserved) {
1950 break;
1951 }
1953 }
1954
1955 bool rejectedAfterShutdown = false;
1956 if (shutdownObserved) {
1957 rejectedAfterShutdown = !target->sendEvent(&postShutdownEvent);
1958 if (!rejectedAfterShutdown) {
1959 target->cullEvent(&postShutdownEvent);
1960 }
1961 }
1962
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;
1970}
1971#endif
1972
1973void Thread::inhibitEvent(size_t eventNumber, bool bInhibit) {
1975 if (bInhibit)
1976 m_StateLevels[m_nStateLevel].m_InhibitMask->set(eventNumber);
1977 else
1978 m_StateLevels[m_nStateLevel].m_InhibitMask->clear(eventNumber);
1979}
1980
1983 return m_StateLevels[m_nStateLevel].m_SignalMask;
1984}
1985
1986void Thread::setSignalMask(uint64_t mask) {
1988 m_StateLevels[m_nStateLevel].m_SignalMask = mask;
1989}
1990
1993 const StateLevel& state = m_StateLevels[m_nStateLevel];
1994 return state.m_DeferredSignalMaskRestore ? state.m_SavedSignalMask : state.m_SignalMask;
1995}
1996
1999 StateLevel& state = m_StateLevels[m_nStateLevel];
2000 state.m_SignalMask = mask;
2001 if (state.m_DeferredSignalMaskRestore) {
2002 state.m_SavedSignalMask = 0;
2003 state.m_DeferredSignalMaskRestore = false;
2004 }
2005}
2006
2007void Thread::restoreDeferredSignalMask(size_t stateLevel) {
2009 if (stateLevel >= MAX_NESTED_EVENTS) {
2010 FATAL("Deferred signal mask restored from an invalid Thread state level.");
2011 }
2012
2013 StateLevel& state = m_StateLevels[stateLevel];
2014 if (state.m_DeferredSignalMaskRestore) {
2015 state.m_SignalMask = state.m_SavedSignalMask;
2016 state.m_SavedSignalMask = 0;
2017 state.m_DeferredSignalMaskRestore = false;
2018 }
2019}
2020
2021void Thread::setCurrentSignalDelivery(size_t signalNumber, size_t continuationEpoch) {
2023 StateLevel& state = m_StateLevels[m_nStateLevel];
2024 state.m_DispatchedSignalNumber = signalNumber;
2025 state.m_DispatchedSignalContinuationEpoch = continuationEpoch;
2026}
2027
2028bool Thread::getCurrentSignalDelivery(size_t& signalNumber, size_t& continuationEpoch) {
2030 const StateLevel& state = m_StateLevels[m_nStateLevel];
2031 if (!state.m_DispatchedSignalNumber) {
2032 return false;
2033 }
2034
2035 signalNumber = state.m_DispatchedSignalNumber;
2036 continuationEpoch = state.m_DispatchedSignalContinuationEpoch;
2037 return true;
2038}
2039
2041 const size_t execStateLevel = getStateLevel();
2042 uint64_t effectiveSignalMask = 0;
2043 {
2045 if (m_nStateLevel != execStateLevel) {
2046 FATAL("Thread state changed during exec signal preparation.");
2047 }
2048 const StateLevel& state = m_StateLevels[execStateLevel];
2049 effectiveSignalMask =
2050 state.m_DeferredSignalMaskRestore ? state.m_SavedSignalMask : state.m_SignalMask;
2051 }
2052
2053 // JumpToUserspace collapses nested states but deliberately retains level
2054 // zero. Every lower physical stack is nevertheless abandoned by exec, so
2055 // retire records from deepest to shallowest before their storage vanishes.
2056 // The exec Uninterruptible lives at execStateLevel and remains armed here.
2057 for (size_t level = execStateLevel; level > 0; --level) {
2058 retireDeferredScopes(false, level - 1);
2059 }
2060
2062 if (m_nStateLevel != execStateLevel) {
2063 FATAL("Thread state changed during exec signal preparation.");
2064 }
2065
2066 StateLevel& base = m_StateLevels[0];
2067 base.m_SignalMask = effectiveSignalMask;
2068 base.m_SavedSignalMask = 0;
2069 base.m_TemporarySignalMaskActive = false;
2070 base.m_TemporarySignalWaitInterrupted = false;
2071 base.m_DeferredSignalMaskRestore = false;
2072 base.m_DispatchedSignalNumber = 0;
2073 base.m_DispatchedSignalContinuationEpoch = 0;
2074 base.m_bOwnsAlternateSignalStack = false;
2075 base.m_InterruptionReason = NotInterrupted;
2076 base.m_bDispatchingWaitEvent = false;
2078}
2079
2080size_t Thread::beginTemporarySignalMask(uint64_t signalMask) {
2081 if (this != Processor::information().getCurrentThread()) {
2082 FATAL("Temporary signal mask armed for a non-current Thread.");
2083 }
2084
2086 const size_t stateLevel = m_nStateLevel;
2087 if (stateLevel >= MAX_NESTED_EVENTS) {
2088 FATAL("Temporary signal mask armed on an invalid Thread state level.");
2089 }
2090
2091 StateLevel& state = m_StateLevels[stateLevel];
2092 if (state.m_TemporarySignalMaskActive || state.m_DeferredSignalMaskRestore) {
2093 FATAL("Thread state already owns a temporary signal mask.");
2094 }
2095
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;
2101 return stateLevel;
2102}
2103
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.");
2108 }
2109
2110 StateLevel& state = m_StateLevels[stateLevel];
2111 if (!state.m_TemporarySignalMaskActive) {
2112 FATAL("Thread state has no temporary signal mask to restore.");
2113 }
2114
2115 const bool interrupted = state.m_TemporarySignalWaitInterrupted;
2116 bool deferRestore = false;
2117 if (deferForUserReturn && interrupted && stateLevel == m_nStateLevel) {
2118 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2119 Event* event = *it;
2120 if (event->isSignalEvent() && eventNeedsUserReturnFrameUnlocked(event) &&
2121 eventIsDeliverableUnlocked(event, EventSelection::AnyDeliverable)) {
2122 deferRestore = true;
2123 break;
2124 }
2125 }
2126 }
2127 if (deferRestore)
2128 markUserReturnWorkPending();
2129 // Keep a temporarily unblocked signal eligible until the syscall boundary
2130 // can save the original mask in its handler's return frame.
2131 state.m_DeferredSignalMaskRestore = deferRestore;
2132 if (!deferRestore) {
2133 state.m_SignalMask = state.m_SavedSignalMask;
2134 state.m_SavedSignalMask = 0;
2135 }
2136 state.m_TemporarySignalMaskActive = false;
2137 state.m_TemporarySignalWaitInterrupted = false;
2138 if (interrupted && state.m_InterruptionReason == InterruptedBySignal) {
2139 state.m_InterruptionReason = NotInterrupted;
2140 }
2141 return interrupted;
2142}
2143
2146 const StateLevel& state = m_StateLevels[m_nStateLevel];
2147 return state.m_TemporarySignalMaskActive && state.m_TemporarySignalWaitInterrupted &&
2148 state.m_InterruptionReason == InterruptedBySignal;
2149}
2150
2153 return m_StateLevels[m_nStateLevel].m_TemporarySignalMaskActive;
2154}
2155
2157 const bool interruptsWereEnabled = Processor::getInterrupts();
2159 m_Lock.acquire();
2160 StateLevel& state = m_StateLevels[m_nStateLevel];
2161 const bool retained = state.m_TemporarySignalMaskActive &&
2162 state.m_TemporarySignalWaitInterrupted &&
2163 state.m_InterruptionReason == InterruptedBySignal;
2164 if (!retained) {
2165 state.m_InterruptionReason = NotInterrupted;
2166 }
2167 m_Lock.release();
2168 Processor::setInterrupts(interruptsWereEnabled);
2169 return retained;
2170}
2171
2173 size_t removed = 0;
2174 {
2176
2178 if (*it == pEvent) {
2179 it = m_EventQueue.erase(it);
2180 ++removed;
2181 } else {
2182 ++it;
2183 }
2184 }
2185 }
2186
2187 // The caller retains ownership of an exact-event cull. Account for every
2188 // enqueue independently, including duplicate enqueues of the same object.
2189 while (removed--) {
2190 pEvent->deregisterThread(this);
2191 }
2192}
2193
2194void Thread::cullEvent(size_t eventNumber) {
2195 Vector<Event*> deregisterEvents;
2196
2197 {
2199
2201 if ((*it)->getNumber() == eventNumber) {
2202 Event* pEvent = *it;
2203 it = m_EventQueue.erase(it);
2204 deregisterEvents.pushBack(pEvent);
2205 } else
2206 ++it;
2207 }
2208 }
2209
2210 // clean up events now that we're no longer locked
2211 for (auto it : deregisterEvents) {
2212 it->completeDelivery(this);
2213 }
2214}
2215
2216void Thread::cullSignalEvent(size_t signalNumber) {
2217 Vector<Event*> deregisterEvents;
2218
2219 {
2221
2223 if ((*it)->isSignalEvent() && (*it)->getNumber() == signalNumber) {
2224 Event* pEvent = *it;
2225 it = m_EventQueue.erase(it);
2226 deregisterEvents.pushBack(pEvent);
2227 } else {
2228 ++it;
2229 }
2230 }
2231 }
2232
2233 for (auto it : deregisterEvents) {
2234 it->completeDelivery(this);
2235 }
2236}
2237
2239 if (&target == this) {
2240 return true;
2241 }
2242 TerminationDeferral transferDeferral;
2243 while (true) {
2244 Event* pending = nullptr;
2245 {
2247 for (auto it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2248 if ((*it)->isSignalEvent() && static_cast<SignalEvent*>(*it)->isProcessDirected()) {
2249 pending = *it;
2250 m_EventQueue.erase(it);
2251 break;
2252 }
2253 }
2254 }
2255 if (!pending) {
2256 return true;
2257 }
2258
2259 // The old registration pins the event through destination admission and
2260 // coalescing, including when the destination already holds this signal.
2261 if (!target.sendEvent(pending)) {
2263 m_EventQueue.pushFront(pending);
2264 return false;
2265 }
2266 pending->completeDelivery(this);
2267 }
2268}
2269
2270bool Thread::replaceSignalEvent(size_t signalNumber, Event* replacement, int processDirected,
2271 uint64_t rebindGeneration) {
2272 if (!replacement || !replacement->isSignalEvent() || replacement->getNumber() != signalNumber) {
2273 return false;
2274 }
2275
2276 Event::SendLease eventSendLease = replacement->beginSend();
2277 if (!eventSendLease) {
2278 return false;
2279 }
2280
2281 {
2282 auto senderGuard = m_EventSenderDrainWaiters.acquire();
2284 if (m_bShutdown || m_Status == Zombie) {
2285 return false;
2286 }
2288 }
2289
2290 const bool eventRegistered = replacement->registerThread(this);
2291 Event* previous = nullptr;
2292 if (eventRegistered) {
2293 auto eventWaitGuard = m_EventWaiters.acquire();
2295 if (!m_bShutdown && m_Status != Zombie) {
2296 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
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))) {
2302 previous = *it;
2303 SignalEvent* oldSignal = static_cast<SignalEvent*>(previous);
2304 SignalEvent* newSignal = static_cast<SignalEvent*>(replacement);
2305 newSignal->setProcessDirected(oldSignal->isProcessDirected());
2306 newSignal->setSignalOrigin(oldSignal->getSignalCode(), oldSignal->getSenderProcess(),
2307 oldSignal->getSenderUser());
2308 newSignal->setContinuationEpoch(oldSignal->getContinuationEpoch());
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);
2315 *it = replacement;
2316 break;
2317 }
2318 }
2319 }
2320 }
2321
2322 if (eventRegistered && !previous) {
2323 replacement->deregisterThread(this);
2324 }
2325 if (previous) {
2326 previous->completeDelivery(this);
2327 }
2328
2329 {
2330 auto senderGuard = m_EventSenderDrainWaiters.acquire();
2331 bool drained = false;
2332 {
2334 assert(m_EventSendersInFlight);
2335 drained = !--m_EventSendersInFlight;
2336 }
2337 if (drained) {
2338 senderGuard.wakeAll(WaitQueue::WakeReason::Signalled, WaitQueue::Channel(this));
2339 }
2340 }
2341
2342 return previous != nullptr;
2343}
2344
2345bool Thread::hasSignalEvent(size_t signalNumber, int processDirected) {
2347
2348 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2349 if ((*it)->isSignalEvent() && (*it)->getNumber() == signalNumber &&
2350 (processDirected < 0 ||
2351 static_cast<SignalEvent*>(*it)->isProcessDirected() == (processDirected != 0))) {
2352 return true;
2353 }
2354 }
2355 return false;
2356}
2357
2358bool Thread::acceptingEvents() {
2360 return !m_bShutdown && m_Status != Zombie;
2361}
2362
2363void Thread::setSynchronousSignalMask(uint64_t mask) {
2365 m_SynchronousSignalMask = mask;
2366}
2367
2368uint64_t Thread::getSynchronousSignalMask() {
2370 return m_SynchronousSignalMask;
2371}
2372
2373uint64_t Thread::pendingSignalMask(bool processOnly) {
2375 uint64_t mask = 0;
2376 for (Event* event : m_EventQueue) {
2377 if (!event->isSignalEvent() || !event->getNumber() || event->getNumber() > 64) {
2378 continue;
2379 }
2380 auto* signal = static_cast<SignalEvent*>(event);
2381 if (signal->deliveryActive() && (!processOnly || signal->isProcessDirected())) {
2382 mask |= uint64_t(1) << (signal->getNumber() - 1);
2383 }
2384 }
2385 return mask;
2386}
2387
2388uint64_t Thread::pendingSignalOrder(size_t number, bool processOnly) {
2390 uint64_t sequence = ~uint64_t(0);
2391 for (Event* event : m_EventQueue) {
2392 if (!event->isSignalEvent() || event->getNumber() != number)
2393 continue;
2394 auto* signal = static_cast<SignalEvent*>(event);
2395 if (signal->deliveryActive() && (!processOnly || signal->isProcessDirected()) &&
2396 signal->queueSequence() < sequence)
2397 sequence = signal->queueSequence();
2398 }
2399 return sequence;
2400}
2401
2402Event::Delivery Thread::reservePendingSignal(uint64_t mask, bool processOnly,
2403 uint64_t expectedSequence) {
2405 auto selected = m_EventQueue.end();
2406 for (auto it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2407 Event* event = *it;
2408 if (!event->isSignalEvent() || !event->getNumber() || event->getNumber() > 64) {
2409 continue;
2410 }
2411 auto* signal = static_cast<SignalEvent*>(event);
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()))) {
2417 selected = it;
2418 }
2419 }
2420 if (selected == m_EventQueue.end()) {
2421 return Event::Delivery();
2422 }
2423 Event* event = *selected;
2424 if (expectedSequence != ~uint64_t(0) &&
2425 static_cast<SignalEvent*>(event)->queueSequence() != expectedSequence)
2426 return Event::Delivery();
2427 m_EventQueue.erase(selected);
2428 return Event::Delivery(event, this);
2429}
2430
2431bool Thread::restorePendingSignal(Event::Delivery& delivery) {
2432 if (!delivery || delivery.m_pThread != this || delivery.m_bActive) {
2433 return false;
2434 }
2435 {
2436 auto waitGuard = m_EventWaiters.acquire();
2438 if (m_bShutdown || m_Status == Zombie)
2439 return false;
2440 m_EventQueue.pushFront(delivery.m_pEvent);
2441 delivery.m_pEvent = nullptr;
2442 delivery.m_pThread = nullptr;
2443 }
2445 return true;
2446}
2447
2448void Thread::cullSignalSource(const void* source) {
2449 Vector<Event*> retiring;
2450 {
2452 for (auto it = m_EventQueue.begin(); it != m_EventQueue.end();) {
2453 if ((*it)->isSignalEvent() && static_cast<SignalEvent*>(*it)->deliverySource() == source) {
2454 retiring.pushBack(*it);
2455 it = m_EventQueue.erase(it);
2456 } else {
2457 ++it;
2458 }
2459 }
2460 }
2461 for (Event* event : retiring) {
2462 event->completeDelivery(this);
2463 }
2464}
2465
2466Event::Delivery Thread::getNextEvent(EventSelection selection) {
2467 Event* pResult = nullptr;
2468
2469 {
2471
2472 if (__atomic_load_n(&m_EventDeferralDepth, __ATOMIC_ACQUIRE)) {
2473 return Event::Delivery();
2474 }
2475
2476 auto selected = m_EventQueue.end();
2477 for (auto it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2478 Event* event = *it;
2479 if (!eventIsDeliverableUnlocked(event, selection)) {
2480 continue;
2481 }
2482 if (selected == m_EventQueue.end()) {
2483 selected = it;
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()))) {
2489 selected = it;
2490 }
2491 if (!event->isSignalEvent()) {
2492 break;
2493 }
2494 }
2495 if (selected != m_EventQueue.end()) {
2496 pResult = *selected;
2497 m_EventQueue.erase(selected);
2498 }
2499 }
2500
2501 return pResult ? Event::Delivery(pResult, this) : Event::Delivery();
2502}
2503
2504bool Thread::hasEvents() {
2506
2507 return hasEventsUnlocked();
2508}
2509
2510bool Thread::eventIsDeliverableUnlocked(Event* event, EventSelection selection) {
2511 const size_t eventNumber = event->getNumber();
2512 if (m_UserReturnSignalParked && event->isSignalEvent() && eventNumber != 9)
2513 return false;
2514 if (event->isSignalEvent() &&
2515 (!static_cast<SignalEvent*>(event)->deliveryActive() ||
2516 (eventNumber > 0 && eventNumber <= 64 &&
2517 (m_SynchronousSignalMask & (uint64_t(1) << (eventNumber - 1)))))) {
2518 return false;
2519 }
2520 const bool signalInhibited =
2521 event->isSignalEvent() && eventNumber > 0 && eventNumber <= 64 &&
2522 (m_StateLevels[m_nStateLevel].m_SignalMask & (static_cast<uint64_t>(1) << (eventNumber - 1)));
2523 const bool exactUserReturnUnavailable =
2524 (selection == EventSelection::WithoutExactUserReturn &&
2526 (selection != EventSelection::AnyDeliverable && m_SignalFramesRequired &&
2527 event->isSignalEvent() && eventNumber != 9 &&
2528 !m_StateLevels[m_nStateLevel].m_UserReturnFrame);
2529 bool processBlocksEvent = false;
2530 if (selection == EventSelection::StoppedProcessKernel) {
2531 // This policy is selected only after the caller has observed Suspended
2532 // under the event-wait handshake. Do not re-read Process state here: a
2533 // concurrent resume must not broaden this dequeue to a user handler.
2534 processBlocksEvent = event->getHandlerPrivilege() != Event::HandlerPrivilege::Kernel ||
2535 !event->isDeliverableWhileProcessSuspended();
2536 } else {
2537 const Process::ProcessState processState = m_pParent ? m_pParent->getState() : Process::Active;
2538 processBlocksEvent =
2539 (selection == EventSelection::KernelDeliverable &&
2540 event->getHandlerPrivilege() != Event::HandlerPrivilege::Kernel) ||
2541 (processState != Process::Active &&
2542 event->getHandlerPrivilege() == Event::HandlerPrivilege::User) ||
2543 (processState == Process::Suspended && !event->isDeliverableWhileProcessSuspended());
2544 }
2545 return !m_StateLevels[m_nStateLevel].m_InhibitMask->test(eventNumber) && !signalInhibited &&
2546 !exactUserReturnUnavailable && !processBlocksEvent &&
2547 (event->getSpecificNestingLevel() == ~0UL ||
2548 event->getSpecificNestingLevel() == m_nStateLevel);
2549}
2550
2552 auto eventWaitGuard = m_EventWaiters.acquire();
2554
2555 bool caughtSignalDeferred = false;
2556 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2557 Event* event = *it;
2558 if (event->isSignalEvent() && eventNeedsUserReturnFrameUnlocked(event) &&
2559 eventIsDeliverableUnlocked(event, EventSelection::AnyDeliverable)) {
2560 caughtSignalDeferred = true;
2561 break;
2562 }
2563 }
2564 if (!caughtSignalDeferred) {
2565 return;
2566 }
2567
2568 StateLevel& current = m_StateLevels[m_nStateLevel];
2569 if (current.m_bDispatchingWaitEvent) {
2570 current.m_InterruptionReason = InterruptedBySignal;
2571 }
2572
2573 // Unlike the generic event trampoline, this path does not push a state
2574 // level. Include the current level when locating a temporary-mask owner.
2575 for (size_t level = m_nStateLevel + 1; level > 0; --level) {
2576 StateLevel& owner = m_StateLevels[level - 1];
2577 if (!owner.m_TemporarySignalMaskActive) {
2578 continue;
2579 }
2580
2581 owner.m_InterruptionReason = InterruptedBySignal;
2582 owner.m_TemporarySignalWaitInterrupted = true;
2583 break;
2584 }
2585}
2586
2587bool Thread::hasEventsUnlocked(EventSelection selection) {
2588 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2589 if (eventIsDeliverableUnlocked(*it, selection)) {
2590 return true;
2591 }
2592 }
2593
2594 return false;
2595}
2596
2597bool Thread::hasDeliverableEventsUnlocked(EventSelection selection) {
2598 return !__atomic_load_n(&m_EventDeferralDepth, __ATOMIC_ACQUIRE) && hasEventsUnlocked(selection);
2599}
2600
2602 bool wakeThread = false;
2603 PerProcessorScheduler* readyScheduler = nullptr;
2604 {
2605 auto eventWaitGuard = m_EventWaiters.acquire();
2607 if (!m_bShutdown && m_Status != Zombie && hasDeliverableEventsUnlocked()) {
2608 wakeThread = interruptWaitUnlocked(WaitQueue::WakeReason::Event, readyScheduler);
2609 }
2610 }
2611
2612 if (wakeThread) {
2613 assert(readyScheduler);
2614 readyScheduler->publishReadyFromWait(this);
2615 }
2616}
2617
2620
2621 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2622 if ((*it) == pEvent) {
2623 return true;
2624 }
2625 }
2626
2627 return false;
2628}
2629
2630bool Thread::hasEvent(size_t eventNumber) {
2632
2633 for (List<Event*>::Iterator it = m_EventQueue.begin(); it != m_EventQueue.end(); ++it) {
2634 if ((*it)->getNumber() == eventNumber) {
2635 return true;
2636 }
2637 }
2638
2639 return false;
2640}
2641
2643
2645 if (!m_StateLevels[0].m_pKernelStack)
2646 return 0;
2647
2648 // Solves a problem where threads are created pointing to different address
2649 // spaces than the process that creates them (for whatever reason). Because
2650 // this is usually only called right after the address space switch in
2651 // PerProcessorScheduler, the address space is set properly.
2652 if (!m_pTlsBase && !m_bTlsBaseOverride) {
2653 // Get ourselves some space.
2654 uintptr_t base = 0;
2656 m_pParent->allocateUserRange(Process::UserRegion::Dynamic, THREAD_TLS_SIZE, base);
2657 else
2658 m_pParent->allocateUserRange(Process::UserRegion::Normal, THREAD_TLS_SIZE, base);
2659
2660 if (!base) {
2661 // Failed to allocate space.
2662 NOTICE("Thread [" << Dec << m_pParent->getId() << ":" << m_Id << Hex
2663 << "]: failed to allocate TLS area.");
2664 return base;
2665 }
2666
2667 // Map.
2668 physical_uintptr_t phys = PhysicalMemoryManager::instance().allocatePage();
2670 phys, reinterpret_cast<void*>(base),
2672
2673 // Set up our thread ID to start with in the TLS region, now that it's
2674 // actually mapped into the address space.
2675 m_pTlsBase = reinterpret_cast<void*>(base);
2676 uint32_t* tlsBase = reinterpret_cast<uint32_t*>(m_pTlsBase);
2677#if BITS_64
2678 *tlsBase = static_cast<uint32_t>(m_Id);
2679#else
2680 *tlsBase = m_Id;
2681#endif
2682
2683#if VERBOSE_KERNEL
2684 NOTICE("Thread [" << Dec << m_pParent->getId() << ":" << m_Id << Hex
2685 << "]: allocated TLS area at " << m_pTlsBase << ".");
2686#endif
2687 }
2688 return reinterpret_cast<uintptr_t>(m_pTlsBase);
2689}
2690
2692 // The scheduler queries the base while restoring an interrupted Thread, so
2693 // the old value must not be unpublished until remapping is non-preemptible.
2694 EnsureInterrupts interrupts(false);
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);
2700 }
2701#endif
2702 m_pTlsBase = 0;
2703 m_bTlsBaseOverride = false;
2704#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2705 if (hook && hookTarget == this) {
2706 hook(this, TlsResetCleared, 0);
2707 }
2708#endif
2709 const uintptr_t tlsBase = getTlsBase();
2710 Processor::setTlsBase(tlsBase);
2711#if X64 && !HOSTED
2712 m_UserGsBase = 0;
2713 Processor::setUserGsBase(0);
2714#endif
2715#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2716 if (hook && hookTarget == this) {
2717 hook(this, TlsResetRemapped, tlsBase);
2718 }
2719#endif
2720}
2721
2722void Thread::setTlsBase(uintptr_t base) {
2724 m_bTlsBaseOverride = true;
2725 m_pTlsBase = reinterpret_cast<void*>(base);
2726
2727 if (Processor::information().getCurrentThread() == this) {
2729 }
2730}
2731
2732#if X64 && !HOSTED
2733void Thread::setUserGsBase(uintptr_t base) {
2734 EnsureInterrupts interrupts(false);
2735 m_UserGsBase = base;
2736 if (Processor::information().getCurrentThread() == this)
2737 Processor::setUserGsBase(base);
2738}
2739
2740void Thread::saveUserGsBase() {
2741 // A userspace selector load can change the base without arch_prctl.
2742 m_UserGsBase = Processor::getUserGsBase();
2743}
2744#endif
2745
2747 return joinInternal(false);
2748}
2749
2751 TerminationDeferral terminationDeferral;
2752 return joinInternal(true);
2753}
2754
2755bool Thread::joinInternal(bool completion) {
2756 Thread* pThisThread = Processor::information().getCurrentThread();
2757 if (pThisThread == this) {
2758 return false;
2759 }
2760
2761 Process* pParent = nullptr;
2762 {
2763 auto guard = m_JoinWaiters.acquire();
2764 if (m_bDetached || m_bJoinClaimed) {
2765 return false;
2766 }
2767 pParent = m_pParent;
2768 if (!pParent->beginThreadJoin()) {
2769 return false;
2770 }
2771 m_bJoinClaimed = true;
2772 }
2773
2774 JoinDiscardContext discard = {this, pParent, true};
2775 StackDiscardScope discardScope(&Thread::discardJoin, &discard);
2776 while (true) {
2777 bool reapable = false;
2778 {
2779 auto guard = m_JoinWaiters.acquire();
2780 if (m_bReapable) {
2781 reapable = true;
2782 } else {
2783 const uintptr_t returnAddress = reinterpret_cast<uintptr_t>(__builtin_return_address(0));
2784 WaitQueue::WakeReason reason =
2785 completion
2786 ? guard.waitForCompletion(WaitQueue::Channel(), Thread::Joining, returnAddress)
2787 : guard.wait(WaitQueue::Channel(), Thread::Joining, returnAddress);
2788 if (reason == WaitQueue::WakeReason::Unwinding ||
2789 reason == WaitQueue::WakeReason::Terminating) {
2790 if (completion) {
2791 continue;
2792 }
2793 discardScope.disarm();
2794 discard.claimed = false;
2795 {
2796 auto claimGuard = m_JoinWaiters.acquire();
2797 m_bJoinClaimed = false;
2798 }
2799 pParent->endThreadJoin();
2800 return false;
2801 }
2802 }
2803 }
2804
2805 if (!reapable) {
2806 continue;
2807 }
2808
2809#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
2810 JoinOperationHook hook = __atomic_load_n(&g_JoinOperationHook, __ATOMIC_ACQUIRE);
2811 if (hook) {
2812 hook(this, pParent);
2813 }
2814#endif
2815
2816 // No new external inspector may enter once final retirement begins.
2817 // Existing inspectors finish before the target can be deleted.
2819
2820 // Serialise the final ownership decision with Process::kill. The active
2821 // join operation pins the parent while deletion runs after this lock.
2822 bool processOwnsTarget = false;
2823 {
2824 RecursingLockGuard<Spinlock> processGuard(pParent->m_Lock);
2825 {
2826 auto claimGuard = m_JoinWaiters.acquire();
2827 if (!m_bReapable) {
2828 continue;
2829 }
2830 if (m_bProcessExitOwned) {
2831 m_bJoinClaimed = false;
2832 processOwnsTarget = true;
2833 }
2834 }
2835
2836 // No callback can observe the target after the ownership decision
2837 // below deletes it. From here, ordinary code owns the claim release.
2838 discardScope.disarm();
2839 discard.claimed = false;
2840 }
2841
2842 if (!processOwnsTarget) {
2843 requireThreadDestructionContext();
2844 delete this;
2845 }
2846
2847 pParent->endThreadJoin();
2848 return !processOwnsTarget;
2849 }
2850}
2851
2855 return false;
2856 }
2857
2859 return true;
2860}
2861
2863 bool wake = false;
2864 bool finalRelease = false;
2865 bool finishDetachedRetirement = false;
2866 {
2868 if (!m_nExternalLeases) {
2869 FATAL("Thread external lease underflow.");
2870 }
2871
2873 finalRelease = !m_nExternalLeases;
2874 finishDetachedRetirement = finalRelease && m_bExternalLeaseAdmissionClosed;
2875 if (finishDetachedRetirement) {
2877 } else {
2878 // Open admission means no drainer can have enrolled yet.
2879 wake = false;
2880 }
2881 }
2882
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);
2887 if (hook) {
2888 hook(this, ExternalLeaseFinalReleaseUnlocked);
2889 }
2890 }
2891#endif
2892
2893 if (wake) {
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);
2898 }
2899#endif
2900 m_ExternalLeaseWaiters.wakeAll(WaitQueue::WakeReason::Signalled, WaitQueue::Channel(this));
2901 }
2902
2903 if (!finishDetachedRetirement) {
2904 // A drainer closes admission under m_ExternalLeaseLock before testing
2905 // this count. An open final release therefore has nobody to wake, and
2906 // must not touch this Thread after the predicate lock is released.
2907 return;
2908 }
2909
2910 // Process::ThreadLease keeps the parent pinned until this method returns.
2911 // Serialising with Process teardown lets the final lease perform deferred
2912 // detached deletion after the scheduler has already switched off-stack.
2913 Process* parent = m_pParent;
2914 bool deleteNow = false;
2915 {
2916 RecursingLockGuard<Spinlock> processGuard(parent->m_Lock);
2917 {
2918 auto joinGuard = m_JoinWaiters.acquire();
2919 deleteNow =
2921 if (deleteNow) {
2923 }
2924 }
2925
2926 {
2929 }
2930
2931 if (!deleteNow) {
2932 // Keep the Process lock until the final queue access is complete.
2933 // Scheduler-side retirement takes the same lock, so it cannot
2934 // delete this Thread between clearing the handoff bit and waking
2935 // a completion waiter.
2936 m_ExternalLeaseWaiters.wakeAll(WaitQueue::WakeReason::Signalled, WaitQueue::Channel(this));
2937 }
2938 }
2939
2940 if (deleteNow) {
2941 requireThreadDestructionContext();
2942 delete this;
2943 }
2944}
2945
2950
2952 TerminationDeferral terminationDeferral;
2953 while (true) {
2954 auto guard = m_ExternalLeaseWaiters.acquire();
2955 {
2959 return;
2960 }
2961 }
2962
2963 const WaitQueue::WakeReason reason = guard.waitForCompletion(
2964 WaitQueue::Channel(this), Thread::Joining, reinterpret_cast<uintptr_t>(this));
2965 (void)reason;
2966 }
2967}
2968
2969void Thread::discardJoin(void* context) {
2970 JoinDiscardContext* discard = reinterpret_cast<JoinDiscardContext*>(context);
2971 if (!discard->claimed) {
2972 return;
2973 }
2974
2975 Thread* target = discard->target;
2976 Process* parent = discard->parent;
2977 discard->claimed = false;
2978 discard->target = nullptr;
2979 discard->parent = nullptr;
2980 {
2981 auto guard = target->m_JoinWaiters.acquire();
2982 target->m_bJoinClaimed = false;
2983 }
2984 parent->endThreadJoin();
2985}
2986
2988 Process* pParent = m_pParent;
2989 if (!pParent->beginThreadJoin()) {
2990 return false;
2991 }
2992
2993 bool deleteNow = false;
2994 bool joinInProgress = false;
2995 {
2996 RecursingLockGuard<Spinlock> processGuard(pParent->m_Lock);
2997 {
2998 auto guard = m_JoinWaiters.acquire();
2999 if (m_bJoinClaimed) {
3000 ERROR(
3001 "Thread::detach() called while other threads are "
3002 "joining.");
3003 joinInProgress = true;
3004 } else {
3005 m_bDetached = true;
3007 if (deleteNow) {
3009 }
3010 }
3011 }
3012 }
3013
3014 if (joinInProgress) {
3015 pParent->endThreadJoin();
3016 return false;
3017 }
3018
3019 if (deleteNow) {
3021 {
3022 RecursingLockGuard<Spinlock> processGuard(pParent->m_Lock);
3023 {
3024 auto guard = m_JoinWaiters.acquire();
3025 deleteNow = deleteNow && m_bDetached && m_bReapable && !m_bProcessExitOwned &&
3027 }
3028 }
3029 if (deleteNow) {
3030 requireThreadDestructionContext();
3031 delete this;
3032 }
3033 }
3034
3035 pParent->endThreadJoin();
3036 return true;
3037}
3038
3039Thread::StateLevel::StateLevel()
3040 : m_State(),
3041 m_pKernelStack(0),
3042 m_pUserStack(0),
3043 m_pAuxillaryStack(0),
3044 m_InhibitMask(),
3045 m_SignalMask(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),
3053 m_Errno(0),
3054 m_InterruptionReason(NotInterrupted),
3055 m_bDispatchingWaitEvent(false),
3056 m_ExecutionContext(ExecutionContext::WaitableThread),
3057 m_pRequestQueueCallback(nullptr),
3058 m_bTerminalWaitCancelledBeforeBlock(false)
3059#if HOSTED
3060 ,
3061 m_HostedSignalDepth(0)
3062#endif
3063{
3064 m_State = new SchedulerState;
3065 ByteSet(m_State, 0, sizeof(SchedulerState));
3067}
3068
3069Thread::StateLevel::~StateLevel() {
3070 delete m_State;
3071}
3072
3073Thread::StateLevel::StateLevel(const Thread::StateLevel& s)
3074 : m_State(),
3075 m_pKernelStack(s.m_pKernelStack),
3076 m_pUserStack(s.m_pUserStack),
3077 m_pAuxillaryStack(s.m_pAuxillaryStack),
3078 m_InhibitMask(),
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),
3087 m_Errno(s.m_Errno),
3088 m_InterruptionReason(s.m_InterruptionReason),
3089 m_bDispatchingWaitEvent(false),
3090 m_ExecutionContext(s.m_ExecutionContext),
3091 m_pRequestQueueCallback(nullptr),
3092 m_bTerminalWaitCancelledBeforeBlock(false)
3093#if HOSTED
3094 ,
3095 m_HostedSignalDepth(0)
3096#endif
3097{
3098 m_State = new SchedulerState(*(s.m_State));
3100}
3101
3102Thread::StateLevel& Thread::StateLevel::operator=(const Thread::StateLevel& s) {
3103 m_State = new SchedulerState(*(s.m_State));
3107 m_TemporarySignalMaskActive = false;
3108 m_TemporarySignalWaitInterrupted = false;
3109 m_DeferredSignalMaskRestore = false;
3111 m_DispatchedSignalContinuationEpoch = 0;
3113 m_Errno = s.m_Errno;
3114 m_InterruptionReason = s.m_InterruptionReason;
3117 m_pRequestQueueCallback = nullptr;
3119#if HOSTED
3120 m_HostedSignalDepth = 0;
3121#endif
3123 return *this;
3124}
3125
3127 const size_t interruptedLevel = m_nStateLevel ? m_nStateLevel - 1 : 0;
3128 m_StateLevels[interruptedLevel].m_InterruptionReason = InterruptedByTimeout;
3129}
3130
3132 auto eventWaitGuard = m_EventWaiters.acquire();
3134 if (!m_nStateLevel) {
3135 return;
3136 }
3137
3138 StateLevel& interrupted = m_StateLevels[m_nStateLevel - 1];
3139 if (interrupted.m_bDispatchingWaitEvent) {
3140 interrupted.m_InterruptionReason = InterruptedBySignal;
3141 }
3142
3143 // A non-signal kernel handler can nest between the blocking syscall and the
3144 // signal handler. The inherited effective mask still belongs to the nearest
3145 // armed ancestor, so retain the interruption there rather than on every
3146 // suspended temporary wait.
3147 for (size_t level = m_nStateLevel; level > 0; --level) {
3148 StateLevel& owner = m_StateLevels[level - 1];
3149 if (!owner.m_TemporarySignalMaskActive) {
3150 continue;
3151 }
3152
3153 owner.m_InterruptionReason = InterruptedBySignal;
3154 owner.m_TemporarySignalWaitInterrupted = true;
3155 break;
3156 }
3157}
3158
3160 return __atomic_load_n(&m_EventDeferralDepth, __ATOMIC_ACQUIRE) != 0;
3161}
3162
3164 const size_t level = __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
3165 if (level >= MAX_NESTED_EVENTS) {
3166 return false;
3167 }
3168
3169 WaitQueue::Waiter& waiter = m_StateLevels[level].m_Waiter;
3170 WaitQueue* queue = waiter.loadQueue();
3171 if (!queue) {
3172 return false;
3173 }
3174
3175 info.queue = queue;
3176 WaitQueue::Channel channel;
3177 if (!waiter.snapshotChannel(channel)) {
3178 return false;
3179 }
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();
3185
3186 // A concurrent wake may unpublish this persistent record. Reject a torn
3187 // snapshot rather than taking the target lock, which may be frozen by the
3188 // kernel debugger.
3189 return waiter.loadQueue() == queue && __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE) == level;
3190}
3191
3192void Thread::deferEvents() {
3193#if PEDIGREE_LATENCY_ACCOUNTING
3194 if (!eventsDeferred()) {
3195 const CpuTimeMode mode = currentTimeAccountingMode();
3196 transitionTime(mode, mode, true);
3197 m_EventDeferralStarted = LatencyAccounting::active() ? Time::getTicks() : 0;
3198 }
3199#endif
3200 __atomic_add_fetch(&m_EventDeferralDepth, static_cast<size_t>(1), __ATOMIC_ACQ_REL);
3201 markUserReturnWorkFlag(UserReturnEventsDeferred);
3202}
3203
3204void Thread::resumeEvents() {
3205 const size_t depth = __atomic_load_n(&m_EventDeferralDepth, __ATOMIC_ACQUIRE);
3206 if (!depth) {
3207 FATAL("Unbalanced event-delivery deferral.");
3208 }
3209#if PEDIGREE_LATENCY_ACCOUNTING
3210 Time::Timestamp deferredWall = 0;
3211 if (depth == 1) {
3212 const CpuTimeMode mode = currentTimeAccountingMode();
3213 transitionTime(mode, mode, true);
3214 if (m_EventDeferralStarted) {
3215 const Time::Timestamp now = Time::getTicks();
3216 deferredWall = now >= m_EventDeferralStarted ? now - m_EventDeferralStarted : 0;
3217 }
3218 }
3219#endif
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);
3225 }
3226 m_EventDeferralStarted = 0;
3227#endif
3228 }
3229}
3230
3231void Thread::deferTermination() {
3232 __atomic_add_fetch(&m_TerminationDeferralDepth, static_cast<size_t>(1), __ATOMIC_ACQ_REL);
3233}
3234
3235void Thread::resumeTermination() {
3236 const size_t depth = __atomic_load_n(&m_TerminationDeferralDepth, __ATOMIC_ACQUIRE);
3237 if (!depth) {
3238 FATAL("Unbalanced terminal-teardown deferral.");
3239 }
3240 __atomic_sub_fetch(&m_TerminationDeferralDepth, static_cast<size_t>(1), __ATOMIC_ACQ_REL);
3241}
3242
3243inline ALWAYS_INLINE void Thread::publishDeferredScope(DeferredScopeRecord& record,
3244 bool termination, bool events,
3245 DeferredScopeRecord::Cleanup cleanup,
3246 void* context) {
3247 const bool interruptsWereEnabled = Processor::getInterrupts();
3249
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);
3253 if (!sequence) {
3254 FATAL("Thread state cleanup sequence exhausted.");
3255 }
3256
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;
3264 if (termination) {
3265 deferTermination();
3266 }
3267 if (events) {
3268 deferEvents();
3269 }
3270
3271 // Only this Thread mutates its chain, with IRQs masked. Synchronous exception
3272 // scopes retire before resuming us; remote terminal requests do not unlink it.
3273 record.next = __atomic_load_n(&m_pDeferredScopes[level], __ATOMIC_ACQUIRE);
3274 __atomic_store_n(&m_pDeferredScopes[level], &record, __ATOMIC_RELEASE);
3275
3276 Processor::setInterrupts(interruptsWereEnabled);
3277}
3278
3279void Thread::registerFreshTerminationDeferral(DeferredScopeRecord& record,
3280 DeferredScopeRecord::Cleanup cleanup, void* context) {
3281 // Fresh storage can combine termination deferral and abandonment cleanup
3282 // without a second stack record or a preliminary zero fill.
3283 publishDeferredScope(record, true, false, cleanup, context);
3284}
3285
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.");
3290 }
3291
3292 publishDeferredScope(record, termination, events, nullptr, nullptr);
3293}
3294
3295void Thread::armStateCleanup(DeferredScopeRecord& record, DeferredScopeRecord::Cleanup cleanup,
3296 void* context) {
3297 if (!cleanup) {
3298 FATAL("State cleanup armed without a callback.");
3299 }
3300
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.");
3304 }
3305
3306 publishDeferredScope(record, false, false, cleanup, context);
3307}
3308
3309inline ALWAYS_INLINE void Thread::unpublishDeferredScope(DeferredScopeRecord& record,
3310 bool deferrals) {
3311 if (!record.armed || record.stateLevel >= MAX_NESTED_EVENTS) {
3312 FATAL("Deferred scope was not registered on this Thread.");
3313 }
3314
3315 const bool interruptsWereEnabled = Processor::getInterrupts();
3317
3318 if (__atomic_load_n(&m_pDeferredScopes[record.stateLevel], __ATOMIC_ACQUIRE) != &record) {
3319 FATAL("Deferred scopes were not released in LIFO order.");
3320 }
3321 __atomic_store_n(&m_pDeferredScopes[record.stateLevel], record.next, __ATOMIC_RELEASE);
3322
3323 if (deferrals) {
3324 if (record.defersTermination) {
3325 resumeTermination();
3326 }
3327 if (record.defersEvents) {
3328 resumeEvents();
3329 }
3330 }
3331 record = DeferredScopeRecord();
3332
3333 Processor::setInterrupts(interruptsWereEnabled);
3334}
3335
3336void Thread::unregisterDeferredScope(DeferredScopeRecord& record) {
3337 unpublishDeferredScope(record, true);
3338}
3339
3340void Thread::disarmStateCleanup(DeferredScopeRecord& record) {
3341 unpublishDeferredScope(record, false);
3342}
3343
3344void Thread::unregisterTerminationDeferral(DeferredScopeRecord& record) {
3345 const bool interruptsWereEnabled = Processor::getInterrupts();
3347 if (!record.armed || !record.defersTermination || record.defersEvents || record.cleanup ||
3348 record.stateLevel >= MAX_NESTED_EVENTS) {
3349 FATAL("Invalid termination deferral retirement.");
3350 }
3351
3352 DeferredScopeRecord* previous = nullptr;
3353 DeferredScopeRecord* current =
3354 __atomic_load_n(&m_pDeferredScopes[record.stateLevel], __ATOMIC_ACQUIRE);
3355 while (current && current != &record) {
3356 previous = current;
3357 current = current->next;
3358 }
3359 if (!current) {
3360 FATAL("Termination deferral was absent from its Thread.");
3361 }
3362
3363 if (previous) {
3364 previous->next = record.next;
3365 } else {
3366 __atomic_store_n(&m_pDeferredScopes[record.stateLevel], record.next, __ATOMIC_RELEASE);
3367 }
3368 resumeTermination();
3369 record = DeferredScopeRecord();
3370
3371 Processor::setInterrupts(interruptsWereEnabled);
3372}
3373
3374void Thread::moveTerminationDeferral(DeferredScopeRecord& from, DeferredScopeRecord& to) {
3375 if (&from == &to || !from.armed || from.stateLevel >= MAX_NESTED_EVENTS) {
3376 FATAL("Moved termination deferral was not registered.");
3377 }
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.");
3381 }
3382
3383 const bool interruptsWereEnabled = Processor::getInterrupts();
3385
3386 DeferredScopeRecord* previous = nullptr;
3387 DeferredScopeRecord* current =
3388 __atomic_load_n(&m_pDeferredScopes[from.stateLevel], __ATOMIC_ACQUIRE);
3389 while (current && current != &from) {
3390 previous = current;
3391 current = current->next;
3392 }
3393 if (!current) {
3394 FATAL("Moved termination deferral was absent from its Thread.");
3395 }
3396
3397 to = from;
3398 if (previous) {
3399 previous->next = &to;
3400 } else {
3401 __atomic_store_n(&m_pDeferredScopes[from.stateLevel], &to, __ATOMIC_RELEASE);
3402 }
3403 from = DeferredScopeRecord();
3404
3405 Processor::setInterrupts(interruptsWereEnabled);
3406}
3407
3408void Thread::retireDeferredScopes(bool allStateLevels, size_t stateLevel) {
3409 retireDeferredScopesMatching(allStateLevels, stateLevel, false, 0);
3410}
3411
3412size_t Thread::stateCleanupCheckpoint() {
3413 return __atomic_load_n(&m_NextStateCleanupSequence, __ATOMIC_ACQUIRE);
3414}
3415
3416void Thread::retireDeferredScopesAfter(size_t checkpoint) {
3417 retireDeferredScopesMatching(true, 0, true, checkpoint);
3418}
3419
3420void Thread::retireDeferredScopesMatching(bool allStateLevels, size_t stateLevel,
3421 bool newerThanCheckpoint, size_t checkpoint) {
3422 DeferredScopeRecord* retired = nullptr;
3423 DeferredScopeRecord* retiredTail = nullptr;
3424
3425 if (!allStateLevels && stateLevel >= MAX_NESTED_EVENTS) {
3426 FATAL("State cleanup retirement has an invalid level.");
3427 }
3428
3429 const bool interruptsWereEnabled = Processor::getInterrupts();
3431
3432 while (true) {
3433 DeferredScopeRecord* candidate = nullptr;
3434 size_t candidateLevel = 0;
3435
3436 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
3437 if (!allStateLevels && level != stateLevel) {
3438 continue;
3439 }
3440
3441 DeferredScopeRecord* head = __atomic_load_n(&m_pDeferredScopes[level], __ATOMIC_ACQUIRE);
3442 if (!head || (newerThanCheckpoint && head->sequence <= checkpoint)) {
3443 continue;
3444 }
3445 if (!head->armed || head->stateLevel != level || !head->sequence) {
3446 FATAL("Corrupt Thread state cleanup publication.");
3447 }
3448 if (!candidate || head->sequence > candidate->sequence) {
3449 candidate = head;
3450 candidateLevel = level;
3451 }
3452 }
3453
3454 if (!candidate) {
3455 break;
3456 }
3457
3458 DeferredScopeRecord* expected = candidate;
3459 if (!__atomic_compare_exchange_n(&m_pDeferredScopes[candidateLevel], &expected, candidate->next,
3460 false, __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
3461 continue;
3462 }
3463
3464 if (candidate->defersTermination) {
3465 resumeTermination();
3466 }
3467 if (candidate->defersEvents) {
3468 resumeEvents();
3469 }
3470 candidate->armed = false;
3471 candidate->next = nullptr;
3472 if (retiredTail) {
3473 retiredTail->next = candidate;
3474 } else {
3475 retired = candidate;
3476 }
3477 retiredTail = candidate;
3478 }
3479
3480 Processor::setInterrupts(interruptsWereEnabled);
3481
3482 while (retired) {
3483 DeferredScopeRecord* next = retired->next;
3484 DeferredScopeRecord::Cleanup cleanup = retired->cleanup;
3485 void* context = retired->context;
3486 *retired = DeferredScopeRecord();
3487 if (cleanup) {
3488 cleanup(context);
3489 }
3490 retired = next;
3491 }
3492}
3493
3494void Thread::armAtomicStateCleanup(AtomicStateCleanupRecord& record,
3495 AtomicStateCleanupRecord::Cleanup cleanup, void* context) {
3496 if (Processor::information().getCurrentThread() != this) {
3497 FATAL("Interrupt/exception cleanup armed for a non-current Thread.");
3498 }
3499 armStateCleanup(record, cleanup, context);
3500}
3501
3502#if HOSTED
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);
3506 return level;
3507}
3508
3509void Thread::leaveHostedSignalHandler(size_t stateLevel) {
3510 if (UNLIKELY(stateLevel >= MAX_NESTED_EVENTS)) {
3511 FATAL_NOLOCK("Hosted signal frame recorded an invalid state level");
3512 return;
3513 }
3514
3515 const size_t previous =
3516 __atomic_fetch_sub(&m_StateLevels[stateLevel].m_HostedSignalDepth, 1, __ATOMIC_ACQ_REL);
3517 if (UNLIKELY(!previous)) {
3518 __atomic_store_n(&m_StateLevels[stateLevel].m_HostedSignalDepth, 0, __ATOMIC_RELEASE);
3519 FATAL_NOLOCK("Hosted Thread signal-frame depth underflowed");
3520 }
3521}
3522#endif
3523
3524void Thread::disarmAtomicStateCleanup(AtomicStateCleanupRecord& record) {
3525 if (Processor::information().getCurrentThread() != this) {
3526 FATAL("Interrupt/exception cleanup disarmed for a non-current Thread.");
3527 }
3528 disarmStateCleanup(record);
3529}
3530
3532 __atomic_store_n(&m_pScheduler, pScheduler, __ATOMIC_RELEASE);
3533}
3534
3535void Thread::cleanStateLevel(size_t level) {
3536 if (__atomic_load_n(&m_pDeferredScopes[level], __ATOMIC_ACQUIRE)) {
3537 FATAL("Thread state stack freed with an armed cleanup record.");
3538 }
3539 if (m_StateLevels[level].m_TemporarySignalMaskActive) {
3540 FATAL("Thread state stack freed with an active temporary signal mask.");
3541 }
3543
3544#if HOSTED
3545 if (__atomic_load_n(&m_StateLevels[level].m_HostedSignalDepth, __ATOMIC_ACQUIRE)) {
3546 FATAL("Thread state stack freed with a live hosted signal frame.");
3547 }
3548#endif
3549
3550 if (m_StateLevels[level].m_Waiter.loadQueue()) {
3551 FATAL("Thread state stack was cleaned while still in a wait queue.");
3552 }
3553
3554 if (m_StateLevels[level].m_pKernelStack) {
3555 VirtualAddressSpace::getKernelAddressSpace().freeStack(m_StateLevels[level].m_pKernelStack);
3556 m_StateLevels[level].m_pKernelStack = 0;
3557 } else if (m_StateLevels[level].m_pAuxillaryStack) {
3558 VirtualAddressSpace::getKernelAddressSpace().freeStack(m_StateLevels[level].m_pAuxillaryStack);
3559 m_StateLevels[level].m_pAuxillaryStack = 0;
3560 }
3561
3562 if (m_StateLevels[level].m_pUserStack && m_pParent) {
3563 // Can't use Processor::getCurrent.. as by the time we're called
3564 // we may have switched address spaces to allow the thread to die.
3565 m_pParent->getAddressSpace()->freeStack(m_StateLevels[level].m_pUserStack);
3566 m_StateLevels[level].m_pUserStack = 0;
3567 }
3568
3569 m_StateLevels[level].m_InhibitMask.reset();
3570 m_StateLevels[level].m_SavedSignalMask = 0;
3571 m_StateLevels[level].m_TemporarySignalWaitInterrupted = false;
3572 m_StateLevels[level].m_DispatchedSignalNumber = 0;
3573 m_StateLevels[level].m_DispatchedSignalContinuationEpoch = 0;
3574 m_StateLevels[level].m_bOwnsAlternateSignalStack = false;
3575 m_StateLevels[level].m_ExecutionContext.reset();
3576 m_StateLevels[level].m_pRequestQueueCallback = nullptr;
3577 m_StateLevels[level].m_bTerminalWaitCancelledBeforeBlock = false;
3578}
3579
3581 bool becameReady = false;
3582 bool queuedBeforeStart = false;
3583 PerProcessorScheduler* readyScheduler = nullptr;
3584 {
3586 __atomic_store_n(&m_UnwindState, ut, __ATOMIC_RELEASE);
3587 queuedBeforeStart = m_Status == Created && ut == TerminateThread;
3588 if (ut != Continue) {
3589 markUserReturnWorkPending();
3590 const bool terminating = ut == TerminateThread;
3591 becameReady = interruptWaitUnlocked(
3592 terminating ? WaitQueue::WakeReason::Terminating : WaitQueue::WakeReason::Unwinding,
3593 readyScheduler);
3594 }
3595 }
3596
3597 if (becameReady) {
3598 assert(readyScheduler);
3599 readyScheduler->publishReadyFromWait(this);
3600 } else if (queuedBeforeStart) {
3601 Scheduler::instance().threadStatusChanged(this);
3602 }
3603}
3604
3606 // Exec can forward a sibling's request. Publish status and cause together
3607 // so a concurrent local failure cannot create a mixed exit reason.
3608 __atomic_store_n(&m_DeferredProcessExitRequest, static_cast<uint32_t>(code), __ATOMIC_RELEASE);
3610}
3611
3612void Thread::deferSignalExit(int signal) {
3613 const uint64_t request = static_cast<uint32_t>(signal) | (static_cast<uint64_t>(1) << 32);
3614 __atomic_store_n(&m_DeferredProcessExitRequest, request, __ATOMIC_RELEASE);
3616}
3617
3619 const uint64_t value =
3620 __atomic_exchange_n(&m_DeferredProcessExitRequest, uint64_t(0), __ATOMIC_ACQ_REL);
3621 DeferredProcessExit request = {static_cast<int32_t>(value), (value >> 32)
3622 ? Subsystem::ExitCause::Signal
3623 : Subsystem::ExitCause::Normal};
3624 return request;
3625}
3626
3627bool Thread::deferSubsystemException(size_t type, uintptr_t faultAddress, uintptr_t errorCode) {
3628 size_t expected = 0;
3629 if (!__atomic_compare_exchange_n(&m_DeferredSubsystemExceptionState, &expected, 1, false,
3630 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE)) {
3631 FATAL_NOLOCK("Nested subsystem exception reached an occupied deferred slot");
3632 return false;
3633 }
3634
3635 m_DeferredSubsystemExceptionType = type;
3636 m_DeferredSubsystemExceptionFaultAddress = faultAddress;
3637 m_DeferredSubsystemExceptionErrorCode = errorCode;
3638 __atomic_store_n(&m_DeferredSubsystemExceptionState, 2, __ATOMIC_RELEASE);
3639 markUserReturnWorkFlag(UserReturnDeferredException);
3640 return true;
3641}
3642
3643bool Thread::takeDeferredSubsystemException(size_t& type, uintptr_t& faultAddress,
3644 uintptr_t& errorCode) {
3645 if (__atomic_load_n(&m_DeferredSubsystemExceptionState, __ATOMIC_ACQUIRE) != 2) {
3646 return false;
3647 }
3648
3649 type = m_DeferredSubsystemExceptionType;
3650 faultAddress = m_DeferredSubsystemExceptionFaultAddress;
3651 errorCode = m_DeferredSubsystemExceptionErrorCode;
3652 __atomic_store_n(&m_DeferredSubsystemExceptionState, 0, __ATOMIC_RELEASE);
3653 clearUserReturnWorkFlag(UserReturnDeferredException);
3654 return true;
3655}
3656
3657bool Thread::interruptWaitUnlocked(WaitQueue::WakeReason reason,
3658 PerProcessorScheduler*& readyScheduler) {
3659 readyScheduler = nullptr;
3661 if (!waiter.loadQueue() || waiter.loadReason() != WaitQueue::WakeReason::Waiting) {
3662 return false;
3663 }
3664
3665 waiter.storeReason(reason);
3666
3667 if (m_Status == Sleeping) {
3668 m_Status = Ready;
3669 __atomic_store_n(&m_ReadyPublicationPending, true, __ATOMIC_RELEASE);
3670 readyScheduler = waiter.scheduler;
3671 assert(readyScheduler);
3672 return true;
3673 }
3674 return false;
3675}
3676
3677bool Thread::hasActiveWaitUnlocked() const {
3678 return m_StateLevels[m_nStateLevel].m_Waiter.loadQueue() != nullptr;
3679}
3680
3681bool Thread::hasActiveWaitAtAnyLevel() const {
3682 for (size_t level = 0; level < MAX_NESTED_EVENTS; ++level) {
3683 if (m_StateLevels[level].m_Waiter.loadQueue()) {
3684 return true;
3685 }
3686 }
3687 return false;
3688}
3689
3690bool Thread::activeWaitPendingUnlocked() const {
3691 const WaitQueue::Waiter& waiter = m_StateLevels[m_nStateLevel].m_Waiter;
3692 return waiter.loadQueue() && waiter.loadReason() == WaitQueue::WakeReason::Waiting;
3693}
3694
3696 assert(level < MAX_NESTED_EVENTS);
3697 StateLevel& state = m_StateLevels[level];
3698 assert(!state.m_Waiter.loadQueue());
3699 assert(state.m_Waiter.loadReason() == WaitQueue::WakeReason::Terminating);
3700 state.m_bTerminalWaitCancelledBeforeBlock = true;
3701}
3702
3703bool Thread::consumeTerminalWaitCancelledBeforeBlockUnlocked() {
3704 StateLevel& state = m_StateLevels[m_nStateLevel];
3705 if (!state.m_bTerminalWaitCancelledBeforeBlock) {
3706 return false;
3707 }
3708
3709 // A new enrolment always clears the marker. Treat any other mismatch as
3710 // stale rather than allowing it to suppress an unrelated sleep.
3712 return !state.m_Waiter.loadQueue() &&
3713 state.m_Waiter.loadReason() == WaitQueue::WakeReason::Terminating;
3714}
3715
3716void Thread::clearTerminalWaitCancelledBeforeBlockUnlocked(size_t level) {
3717 assert(level < MAX_NESTED_EVENTS);
3718 m_StateLevels[level].m_bTerminalWaitCancelledBeforeBlock = false;
3719}
3720
3722 auto guard = m_JoinWaiters.acquire();
3723 m_bReapable = true;
3724 Metrics::increment(Metrics::ThreadReapable);
3725 if (!m_bDetached) {
3726 guard.wakeAll();
3727 }
3728
3729 bool externalLeasesDrained = false;
3730 {
3732 externalLeasesDrained =
3734 }
3735 const bool deleteNow =
3736 m_bDetached && !m_bProcessExitOwned && externalLeasesDrained && !m_bDetachedRetirementClaimed;
3737 if (deleteNow) {
3739 }
3740 return deleteNow;
3741}
3742
3744 if (m_pParent && getTaskId() == m_pParent->getId()) {
3745 return m_pParent->getUserspaceId(space);
3746 }
3747 return m_UserspacePid ? m_UserspacePid->id(space) : 0;
3748}
3749
3750#endif // THREADS
void reset()
Definition Event.cc:159
Definition Event.h:49
void retire()
Definition Event.cc:479
bool registerThread(Thread *thread)
Definition Event.cc:312
void completeDelivery(Thread *thread)
Definition Event.cc:348
HandlerPrivilege getHandlerPrivilege() const
Definition Event.h:236
void deregisterThread(Thread *thread)
Definition Event.cc:321
virtual bool isSignalEvent() const
Definition Event.h:244
SendLease beginSend()
Definition Event.cc:280
virtual size_t getNumber()=0
virtual bool isDeliverableWhileProcessSuspended() const
Definition Event.h:269
virtual size_t serialize(uint8_t *pBuffer)=0
bool test(size_t n) const
void clear(size_t n)
void set(size_t n)
Iterator begin()
Definition List.h:122
::Iterator< T, node_t > Iterator
Definition List.h:67
Iterator end()
Definition List.h:132
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
Definition Process.h:504
ProcessState
Definition Process.h:303
size_t getId()
Definition Process.h:499
void endThreadJoin()
Definition Process.cc:1188
VirtualAddressSpace * getAddressSpace()
Definition Process.h:530
void removeThread(Thread *pThread)
Definition Process.cc:1351
bool beginThreadJoin()
Definition Process.cc:1178
void transferExecProcessSignals(Thread *pThread)
Definition Process.cc:1342
Spinlock m_Lock
Definition Process.h:1204
void threadExiting(Thread *pThread)
Definition Process.cc:1336
size_t addThread(Thread *pThread)
Definition Process.cc:1303
static bool getInterrupts()
static void setTlsBase(uintptr_t newBase)
static ProcessorInformation & information()
static ExecutionContext executionContext()
Definition Processor.cc:109
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)
Definition Scheduler.cc:152
static Scheduler & instance()
Definition Scheduler.h:96
void addThread(Thread *pThread, PerProcessorScheduler &PPSched)
Definition Scheduler.cc:140
void yield()
Definition Scheduler.cc:236
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)
void release()
Definition Spinlock.cc:168
bool acquire(bool recurse=false, bool safe=true)
Definition Spinlock.cc:36
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
Definition Thread.h:1330
ThreadTimeAccounting m_TimeAccounting
Definition Thread.h:1192
void * m_pAllocatedStack
Definition Thread.h:1208
bool m_bDetachedRetirementClaimed
Definition Thread.h:1361
void discardUserStackMetadataForExec()
Definition Thread.cc:981
bool hasActiveTemporarySignalMask()
Definition Thread.cc:2151
void recordTime(CpuTimeMode mode)
Definition Thread.cc:384
WaitQueue m_JoinWaiters
Definition Thread.h:1265
void unlinkWaitsForStackDiscard()
Definition Thread.cc:640
WaitQueue m_EventWaiters
Definition Thread.h:1288
void unexpectedExit()
Definition Thread.cc:2642
Time::Timestamp m_UserTime
Definition Thread.h:1195
void setTlsBase(uintptr_t base)
Definition Thread.cc:2722
void accountTimerTick(Time::Timestamp delta, bool kernelMode)
Definition Thread.cc:422
void setUnwindState(UnwindType ut)
Definition Thread.cc:3580
CpuTimeMode currentTimeAccountingMode() const
Definition Thread.cc:471
void wakeForDeliverableEvents()
Definition Thread.cc:2601
AlternateSignalStack m_AlternateSignalStack
Definition Thread.h:1302
UnwindType
Definition Thread.h:516
@ Continue
No unwind necessary, carry on as normal.
Definition Thread.h:517
@ TerminateThread
Exit only this thread during Process exit.
Definition Thread.h:519
@ Exit
Exit the owning process at the next safe boundary.
Definition Thread.h:518
void publishTimeAccounting(CpuTimeMode mode, Time::Timestamp elapsed)
Definition Thread.cc:435
bool m_bReapable
Definition Thread.h:1370
SchedulerState & state()
Definition Thread.cc:832
static void discardJoin(void *context)
Definition Thread.cc:2969
bool transferProcessSignalsTo(Thread &target)
Definition Thread.cc:2238
size_t m_ActiveSyscalls[serviceEnd]
Definition Thread.h:1307
bool interruptWaitUnlocked(WaitQueue::WakeReason reason, PerProcessorScheduler *&readyScheduler)
Definition Thread.cc:3657
DeferredScopeRecord * m_pDeferredScopes[MAX_NESTED_EVENTS]
Definition Thread.h:1390
volatile Status m_Status
Definition Thread.h:1310
void * getKernelStackBase(size_t *size) const
Definition Thread.cc:1080
void markSignalInterruptedWait()
Definition Thread.cc:3131
AffinityResult waitAffinity(uint64_t generation)
bool replaceSignalEvent(size_t signalNumber, Event *replacement, int processDirected=-1, uint64_t rebindGeneration=0)
Definition Thread.cc:2270
virtual ~Thread()
Definition Thread.cc:475
void markTimeoutInterruptedWait()
Definition Thread.cc:3126
void restoreDeferredSignalMask(size_t stateLevel)
Definition Thread.cc:2007
void cleanStateLevel(size_t level)
Definition Thread.cc:3535
bool hasSignalEvent(size_t signalNumber, int processDirected=-1)
Definition Thread.cc:2345
uint64_t getSignalMask()
Definition Thread.cc:1981
bool getWaitDebugInfo(WaitDebugInfo &info)
Definition Thread.cc:3163
void shutdown()
Definition Thread.cc:570
bool hasEvent(Event *pEvent)
Definition Thread.cc:2618
bool m_bJoinClaimed
Definition Thread.h:1358
static void threadExited() NORETURN
Definition Thread.cc:1030
bool m_bShutdown
Definition Thread.h:1339
bool deferSubsystemException(size_t type, uintptr_t faultAddress, uintptr_t errorCode)
Definition Thread.cc:3627
size_t m_Id
Definition Thread.h:1211
void deferSignalExit(int signal)
Definition Thread.cc:3612
bool m_bStartRequested
Definition Thread.h:1352
bool m_bSubsystemExitNotified
Definition Thread.h:1342
size_t m_EventDeferralDepth
Definition Thread.h:1379
void commitSignalHandlerMask(uint64_t mask)
Definition Thread.cc:1997
void waitForEvent(WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
Definition Thread.cc:1202
Process * m_pParent
Definition Thread.h:1180
bool joinForCompletion()
Definition Thread.cc:2750
WaitQueue m_ExternalLeaseWaiters
Definition Thread.h:1271
bool m_bTlsBaseOverride
Definition Thread.h:1336
MUST_USE_RESULT Event::Delivery getNextEvent(EventSelection selection=EventSelection::AnyDeliverable)
Definition Thread.cc:2466
int(* ThreadStartFunc)(void *)
Definition Thread.h:189
bool markReapable()
Definition Thread.cc:3721
void * getKernelStack()
Definition Thread.cc:1070
bool join()
Definition Thread.cc:2746
bool m_bExitStarted
Definition Thread.h:1367
bool eventsDeferred() const
Definition Thread.cc:3159
void allocateStackAtLevel(size_t stateLevel)
Definition Thread.cc:1054
UnwindType getUnwindState()
Definition Thread.h:535
bool detach()
Definition Thread.cc:2987
bool m_bDetached
Definition Thread.h:1355
void cullEvent(Event *pEvent)
Definition Thread.cc:2172
bool retainTemporarySignalWaitInterruptionOrClear()
Definition Thread.cc:2156
void endExternalLease()
Definition Thread.cc:2862
void setClearChildTid(uintptr_t address)
Definition Thread.cc:653
DeferredThreadReapNode m_DeferredReapNode
Definition Thread.h:1189
void setKernelStack()
Definition Thread.cc:1099
bool m_bProcessExitOwned
Definition Thread.h:1373
Spinlock m_Lock
Definition Thread.h:1262
bool hasEventsUnlocked(EventSelection selection=EventSelection::AnyDeliverable)
Definition Thread.cc:2587
void trackTime(CpuTimeMode mode)
Definition Thread.cc:392
void setScheduler(class PerProcessorScheduler *pScheduler)
Definition Thread.cc:3531
bool startDetached()
Definition Thread.cc:769
ExecutionContext executionContext() const
Definition Thread.cc:836
Process * getParent() const
Definition Thread.h:340
bool eventNeedsUserReturnFrameUnlocked(Event *event) const
uintptr_t m_RobustList
Definition Thread.h:1348
void closeExternalLeaseAdmission()
Definition Thread.cc:2946
void popState(bool clean=true)
Definition Thread.cc:913
void prepareSignalStateForExec()
Definition Thread.cc:2040
void cullSignalEvent(size_t signalNumber)
Definition Thread.cc:2216
void setSignalMask(uint64_t mask)
Definition Thread.cc:1986
size_t m_nStateLevel
Definition Thread.h:1177
size_t m_nExternalLeases
Definition Thread.h:1274
class PerProcessorScheduler * getScheduler() const
Definition Thread.h:929
Spinlock m_ExternalLeaseLock
Definition Thread.h:1268
Thread(Process *pParent, ThreadStartFunc pStartFunction, void *pParam, void *pStack=0, bool semiUser=false, bool bDontPickCore=false, bool delayedStart=false, const ThreadPlacement *placement=nullptr)
Definition Thread.cc:224
void setStatus(Status s)
Definition Thread.cc:719
bool waitForEventOrSignalInterruption(WaitQueue::StackDiscardCleanup onStackDiscard=nullptr, void *stackDiscardContext=nullptr)
Definition Thread.cc:1207
AffinityResult requestAffinity(const CpuAffinityMask &mask, uint64_t &generation)
DeferredProcessExit takeDeferredProcessExit()
Definition Thread.cc:3618
bool hasTemporarySignalWaitInterruption()
Definition Thread.cc:2144
size_t getUserspaceTaskId(const UserspacePidNamespace *space=nullptr) const
Definition Thread.cc:3743
uint64_t getSignalMaskForReturnFrame()
Definition Thread.cc:1991
bool beginExternalLease()
Definition Thread.cc:2852
bool isTerminationDeferred() const
Definition Thread.h:569
size_t m_EventSendersInFlight
Definition Thread.h:1297
AffinityResult completeAffinityAtSafePoint(bool *waited=nullptr)
bool getCurrentSignalDelivery(size_t &signalNumber, size_t &continuationEpoch)
Definition Thread.cc:2028
void setCurrentSignalDelivery(size_t signalNumber, size_t continuationEpoch)
Definition Thread.cc:2021
SchedulerState * pushState()
Definition Thread.cc:841
bool start()
Definition Thread.cc:751
bool m_bExternalLeaseAdmissionClosed
Definition Thread.h:1277
void abandonAllStates()
Definition Thread.cc:965
bool sendEvent(Event *pEvent)
Definition Thread.cc:1115
void inhibitEvent(size_t eventNumber, bool bInhibit)
Definition Thread.cc:1973
void pokeState(size_t stateLevel, SchedulerState &state)
Definition Thread.cc:1107
void * m_pTlsBase
Definition Thread.h:1249
uintptr_t getTlsBase()
Definition Thread.cc:2644
void markTerminalWaitCancelledBeforeBlockUnlocked(size_t level)
Definition Thread.cc:3695
void notifySubsystemExit()
Definition Thread.cc:547
uintptr_t m_ClearChildTid
Definition Thread.h:1345
size_t getStateLevel() const
Definition Thread.h:316
bool m_bExternalLeaseReleaseInProgress
Definition Thread.h:1285
uint64_t m_DeferredProcessExitRequest
Definition Thread.h:1326
bool joinInternal(bool completion)
Definition Thread.cc:2755
WaitQueue m_EventSenderDrainWaiters
Definition Thread.h:1291
size_t m_TerminationDeferralDepth
Definition Thread.h:1387
void closeExternalLeaseAdmissionAndDrain()
Definition Thread.cc:2951
bool takeDeferredSubsystemException(size_t &type, uintptr_t &faultAddress, uintptr_t &errorCode)
Definition Thread.cc:3643
void resetTlsBase()
Definition Thread.cc:2691
void markDeferredUserReturnSignalInterruption()
Definition Thread.cc:2551
List< Event * > m_EventQueue
Definition Thread.h:1294
void adoptInitialUserStackForExec(VirtualAddressSpace::Stack *stack)
Definition Thread.cc:1018
void deferProcessExit(int code)
Definition Thread.cc:3605
size_t m_CurrentTimeAccountingMode
Definition Thread.h:1199
void abandonCurrentState(bool clean=false)
Definition Thread.cc:956
void transitionTime(CpuTimeMode from, CpuTimeMode to, bool interruptsAlreadyDisabled=false)
Definition Thread.cc:405
A vector / dynamic array.
Definition Vector.h:33
virtual void freeStack(Stack *pStack)=0
virtual Stack * allocateStack()=0
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 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)
Definition WaitQueue.cc:117
@ Dec
Definition Log.h:126
@ Hex
Definition Log.h:124
Iterator erase(Iterator &Iter)
Definition List.h:352
T popFront()
Definition List.h:330
void pushFront(const T &value)
Definition List.h:300
size_t count() const
Definition List.h:212
void pushBack(const T &value)
Definition List.h:216
void pushBack(const T &value)
Definition Vector.h:275
size_t m_DispatchedSignalNumber
Definition Thread.h:1138
VirtualAddressSpace::Stack * m_pKernelStack
Definition Thread.h:1111
WaitQueue::Waiter m_Waiter
Definition Thread.h:1170
uint64_t m_SignalMask
Definition Thread.h:1129
SharedPointer< ExtensibleBitmap > m_InhibitMask
Definition Thread.h:1126
uint64_t m_SavedSignalMask
Definition Thread.h:1132
RequestQueueCallbackScope * m_pRequestQueueCallback
Definition Thread.h:1155
bool m_bOwnsAlternateSignalStack
Definition Thread.h:1142
ExecutionContextState m_ExecutionContext
Definition Thread.h:1152
bool m_bDispatchingWaitEvent
Definition Thread.h:1149
SchedulerState * m_State
Definition Thread.h:1107
VirtualAddressSpace::Stack * m_pAuxillaryStack
Definition Thread.h:1119
bool m_bTerminalWaitCancelledBeforeBlock
Definition Thread.h:1162