The Pedigree Project 0.1
Thread.h
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#ifndef THREAD_H
21#define THREAD_H
22#include "pedigree/kernel/ActivityDiagnostics.h"
23#include "pedigree/kernel/Spinlock.h"
24#include "pedigree/kernel/Subsystem.h"
25#include "pedigree/kernel/compiler.h"
26#include "pedigree/kernel/process/AtomicStateCleanup.h"
27#include "pedigree/kernel/process/CpuAffinity.h"
28#include "pedigree/kernel/process/DeferredScope.h"
29#include "pedigree/kernel/process/DeferredThreadReap.h"
30#include "pedigree/kernel/process/DeferredTimeAccounting.h"
31#include "pedigree/kernel/process/Event.h"
32#include "pedigree/kernel/process/ExecutionContext.h"
33#include "pedigree/kernel/process/ExecutionPersonality.h"
34#include "pedigree/kernel/process/SchedulingAlgorithm.h"
35#include "pedigree/kernel/process/WaitQueue.h"
36#include "pedigree/kernel/processor/ProcessorInformation.h"
37#include "pedigree/kernel/processor/Syscalls.h"
38#include "pedigree/kernel/processor/VirtualAddressSpace.h"
39#include "pedigree/kernel/processor/state_forward.h"
40#include "pedigree/kernel/processor/types.h"
41#include "pedigree/kernel/utilities/List.h"
42#include "pedigree/kernel/utilities/SharedPointer.h"
43#include "pedigree/kernel/utilities/assert.h"
44#include "pedigree/kernel/utilities/new"
45
46#include <config.h>
47
50class Process;
51class UserspacePid;
54class SyscallManager;
59class RoundRobin;
62class UserReturnFrame;
63
65#define THREAD_TLS_SIZE PAGE_SIZE
66
77class EXPORTED_PUBLIC Thread {
78 friend class PerProcessorScheduler;
79 friend class Scheduler;
80 friend class PageFaultHandler;
81 friend class Process;
82 friend class WaitQueue;
83 friend class Uninterruptible;
84 friend class TerminationDeferral;
85 friend class SyscallManager;
86 friend class IrqHandlerRegistry;
87 friend class TimerHandlerRegistry;
88 friend class HostedInterruptManager;
89 friend class RoundRobin;
90 friend class ExecutionContextGuard;
91 friend class RequestQueueCallbackScope;
93
94 public:
95 class EXPORTED_PUBLIC StackDiscardScope {
96 public:
97 StackDiscardScope(DeferredScopeRecord::Cleanup cleanup, void* context);
99
100 void disarm();
101
102 private:
103 NOT_COPYABLE_OR_ASSIGNABLE(StackDiscardScope);
104
105 Thread* m_pThread;
106 DeferredScopeRecord m_Record;
107 };
108
109 class EXPORTED_PUBLIC UserReturnFrameScope {
110 public:
113
114 private:
115 NOT_COPYABLE_OR_ASSIGNABLE(UserReturnFrameScope);
116 static void restore(void* context);
117 Thread* m_Owner;
118 size_t m_StateLevel;
119 UserReturnFrame* m_Frame;
120 UserReturnFrame* m_Previous;
121 DeferredScopeRecord m_Record;
122 };
123
124 UserReturnFrame* currentUserReturnFrame() const;
125 bool tryRequireSignalFrames();
126 void clearSignalFrameRequirement();
127 void setUserReturnSignalParked(bool parked);
128
129 enum UserReturnWorkFlag : size_t {
130 UserReturnExternalWork = 1,
131 UserReturnEventsDeferred = 1 << 1,
132 UserReturnSignalFrames = 1 << 3,
133 UserReturnDeferredException = 1 << 4,
134 UserReturnOriginalSyscall = 1 << 5,
135 };
136
137 bool canSkipUserReturnWork();
138 bool clearUserReturnWorkIfIdle();
139 bool userReturnWorkPending() const {
140 return __atomic_load_n(&m_UserReturnWorkPending, __ATOMIC_ACQUIRE) != 0 ||
141 isTerminationDeferred();
142 }
143 bool requiresSignalFrames() const {
144 return __atomic_load_n(&m_SignalFramesRequired, __ATOMIC_ACQUIRE);
145 }
146
148 class EXPORTED_PUBLIC TemporarySignalMask {
149 public:
150 TemporarySignalMask(Thread& thread, uint64_t signalMask);
152
154 bool finish();
155
156 private:
157 NOT_COPYABLE_OR_ASSIGNABLE(TemporarySignalMask);
158
159 static void discard(void* context);
160
161 Thread* m_pThread;
162 size_t m_StateLevel;
163 DeferredScopeRecord m_Record;
164 };
165
167 enum Status {
168 Created,
169 Ready,
170 Running,
171 Sleeping,
172 Zombie,
173 AwaitingJoin,
174 };
175
178 None,
179 SemWait,
180 CondWait,
181 Joining,
182 FutexWait,
183 EventWait,
184 ProcessWait,
185 CallbackDrain
186 };
187
189 typedef int (*ThreadStartFunc)(void*);
190
209 Thread(Process* pParent, ThreadStartFunc pStartFunction, void* pParam, void* pStack = 0,
210 bool semiUser = false, bool bDontPickCore = false, bool delayedStart = false,
211 const ThreadPlacement* placement = nullptr);
212
215 Thread(Process* pParent);
216
220 Thread(Process* pParent, SyscallState& state, bool delayedStart = false,
221 const ThreadPlacement* placement = nullptr);
222
223 void snapshotPlacement(ThreadPlacement& placement);
224 // Subsystem-owned immutable restrictions survive exec and are shared by a
225 // newly cloned thread until it installs a more restrictive state.
227 public:
228 virtual ~SecurityState() = default;
229 virtual bool interceptSyscall(SyscallState&, uintptr_t&) const = 0;
230 };
232 bool hasSecurityState() const {
233 return __atomic_load_n(&m_HasSecurityState, __ATOMIC_ACQUIRE);
234 }
235 SecurityStateRef securityState();
236 void setSecurityState(const SecurityStateRef& state);
238 void snapshotPlacementLocked(ThreadPlacement& placement) const;
240 AffinityResult requestAffinity(const CpuAffinityMask& mask, uint64_t& generation);
242 AffinityResult waitAffinity(uint64_t generation);
248 AffinityResult completeAffinityAtSafePoint(bool* waited = nullptr);
249 bool affinityWorkPending() const {
250 return __atomic_load_n(&m_AffinityReturnPending, __ATOMIC_ACQUIRE) != 0;
251 }
252#if PEDIGREE_AFFINITY_TESTS
253 using AffinityCommitHook = void (*)(Thread*);
254 static void setAffinityCommitHookForTest(Thread* target, AffinityCommitHook hook);
255#endif
256
261 virtual ~Thread();
262
269 void shutdown();
270
275 void notifySubsystemExit();
276 /* Forces the thread to run on the bootstrap processor. */
277 void forceToStartupProcessor();
278
281 SchedulerState& state();
282
287 SchedulerState* pushState();
288
293 void popState(bool clean = true);
294
296 void abandonCurrentState(bool clean = false);
297
299 void abandonAllStates();
300
301 VirtualAddressSpace::Stack* getStateUserStack();
302
303 void setStateUserStack(VirtualAddressSpace::Stack* st);
304
310 void discardUserStackMetadataForExec();
311
313 void adoptInitialUserStackForExec(VirtualAddressSpace::Stack* stack);
314
316 size_t getStateLevel() const {
317 return __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
318 }
319
320 void* getSyscallDispatchContext() const {
321 return m_SyscallDispatchContext;
322 }
323 void setSyscallDispatchContext(void* context) {
324 m_SyscallDispatchContext = context;
325 }
326
328 void allocateStackAtLevel(size_t stateLevel);
329
331 void setKernelStack();
332
337 void pokeState(size_t stateLevel, SchedulerState& state);
338
341 return m_pParent;
342 }
343
345 void setClearChildTid(uintptr_t address);
346
348 uintptr_t takeClearChildTid() {
349 return __atomic_exchange_n(&m_ClearChildTid, static_cast<uintptr_t>(0), __ATOMIC_ACQ_REL);
350 }
351
352 void setRobustList(uintptr_t address, size_t ownerId);
353
354 uintptr_t getRobustList() const {
355 return __atomic_load_n(&m_RobustList, __ATOMIC_ACQUIRE);
356 }
357
358 uintptr_t takeRobustList(size_t& ownerId);
359
361 void recordTime(CpuTimeMode mode);
362
364 void trackTime(CpuTimeMode mode);
365
367 void transitionTime(CpuTimeMode from, CpuTimeMode to, bool interruptsAlreadyDisabled = false);
368
373 ALWAYS_INLINE void transitionTimeAtInterruptReturn(CpuTimeMode from, CpuTimeMode to) {
374 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
376 // The architecture boundary owns the physical IRQ mask. Going
377 // through CpuTimeSample here could momentarily undo that mask on hosted,
378 // where the logical state intentionally describes the pending sigreturn.
379 const auto sample = Time::sampleCpuTime();
380 const Time::Timestamp elapsed =
381 m_TimeAccounting.elapsedAtInterruptDisabled(from, sample.timestamp, sample.processor);
382 m_TimeAccounting.recordAtInterruptDisabled(to, sample.timestamp, sample.processor);
383 __atomic_store_n(&m_CurrentTimeAccountingMode, static_cast<size_t>(to), __ATOMIC_RELEASE);
384 if (elapsed) {
385 publishTimeAccounting(from, elapsed);
386 }
387 } else {
388 (void)from;
389 __atomic_store_n(&m_CurrentTimeAccountingMode, static_cast<size_t>(to), __ATOMIC_RELEASE);
390 }
391 }
392
394 CpuTimeMode currentTimeAccountingMode() const;
395
397 void accountTimerTick(Time::Timestamp delta, bool kernelMode);
398
399#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
400 static constexpr size_t NoSyscallTimingSlot = ~static_cast<size_t>(0);
401
402 size_t installSyscallTimingSlot(size_t slot) {
403 return __atomic_exchange_n(&m_ActiveSyscallTimingSlot, slot, __ATOMIC_ACQ_REL);
404 }
405
406 void restoreSyscallTimingSlot(size_t slot) {
407 __atomic_store_n(&m_ActiveSyscallTimingSlot, slot, __ATOMIC_RELEASE);
408 }
409#endif
410
412 Time::Timestamp getUserTime() const {
413 return __atomic_load_n(&m_UserTime, __ATOMIC_ACQUIRE);
414 }
415 Time::Timestamp getKernelTime() const {
416 return __atomic_load_n(&m_KernelTime, __ATOMIC_ACQUIRE);
417 }
418
419#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
421 void publishTimeAccountingForHostedTest(Time::Timestamp user, Time::Timestamp system);
422#endif
423
424 void setParent(Process* p) {
425 m_pParent = p;
426 }
427
428 ExecutionPersonality& executionPersonality() {
429 return m_ExecutionPersonality;
430 }
431
434 return m_Status;
435 }
436
443 bool start();
444
451 bool startDetached();
452
455 return m_ExitCode;
456 }
457
459 void* getKernelStack();
460
462 void* getKernelStackBase(size_t* size) const;
463
465 size_t getId() {
466 return m_Id;
467 }
468
470 size_t getUserspaceTaskId(const UserspacePidNamespace* space = nullptr) const;
471
472 size_t getTaskId() const {
473 return __atomic_load_n(&m_TaskId, __ATOMIC_ACQUIRE);
474 }
475
477 size_t getErrno() {
478 return m_StateLevels[m_nStateLevel].m_Errno;
479 }
480
482 void setErrno(size_t err) {
483 m_StateLevels[m_nStateLevel].m_Errno = err;
484 }
485
486 enum InterruptionReason {
487 NotInterrupted,
488 InterruptedByTimeout,
489 InterruptedBySignal,
490 };
491
494 return getInterruptionReason() != NotInterrupted;
495 }
496
497 void clearInterruption() {
498 m_StateLevels[m_nStateLevel].m_InterruptionReason = NotInterrupted;
499 }
500
501 InterruptionReason getInterruptionReason() {
502 return m_StateLevels[m_nStateLevel].m_InterruptionReason;
503 }
504
505 void setInterruptionReason(InterruptionReason reason) {
506 m_StateLevels[m_nStateLevel].m_InterruptionReason = reason;
507 }
508
510 void markTimeoutInterruptedWait();
511
513 void markSignalInterruptedWait();
514
517 Continue = 0,
519 TerminateThread
520 };
521
536 return __atomic_load_n(&m_UnwindState, __ATOMIC_ACQUIRE);
537 }
539 void setUnwindState(UnwindType ut);
540
542 void deferProcessExit(int code);
543
545 void deferSignalExit(int signal);
546
548 int code;
550 };
551
553 DeferredProcessExit takeDeferredProcessExit();
554
559 bool deferSubsystemException(size_t type, uintptr_t faultAddress, uintptr_t errorCode);
560
561 bool hasDeferredSubsystemException() const {
562 return __atomic_load_n(&m_DeferredSubsystemExceptionState, __ATOMIC_ACQUIRE) != 0;
563 }
564
566 bool takeDeferredSubsystemException(size_t& type, uintptr_t& faultAddress, uintptr_t& errorCode);
567
570 return __atomic_load_n(&m_TerminationDeferralDepth, __ATOMIC_ACQUIRE) != 0;
571 }
572
574 DebugState getDebugState(uintptr_t& address) {
575 for (size_t attempt = 0; attempt < 2; ++attempt) {
576 const size_t generation = __atomic_load_n(&m_DebugStateGeneration, __ATOMIC_ACQUIRE);
577 if (generation & 1) {
578 continue;
579 }
580
581 const DebugState state = __atomic_load_n(&m_DebugState, __ATOMIC_RELAXED);
582 const uintptr_t observedAddress = __atomic_load_n(&m_DebugStateAddress, __ATOMIC_RELAXED);
583 if (generation == __atomic_load_n(&m_DebugStateGeneration, __ATOMIC_ACQUIRE)) {
584 address = observedAddress;
585 return state;
586 }
587 }
588
589 address = 0;
590 return None;
591 }
593 void setDebugState(DebugState state, uintptr_t address) {
594 __atomic_add_fetch(&m_DebugStateGeneration, static_cast<size_t>(1), __ATOMIC_ACQ_REL);
595 __atomic_store_n(&m_DebugStateAddress, address, __ATOMIC_RELAXED);
596 __atomic_store_n(&m_DebugState, state, __ATOMIC_RELAXED);
597 __atomic_add_fetch(&m_DebugStateGeneration, static_cast<size_t>(1), __ATOMIC_RELEASE);
598 }
599
601 WaitQueue* queue;
602 const void* channelOwner;
603 uintptr_t channelValue;
604 WaitQueue::WakeReason reason;
605 size_t stateLevel;
606 bool queued;
607 };
608
610 bool getWaitDebugInfo(WaitDebugInfo& info);
611
614 return m_Lock;
615 }
616
624 bool sendEvent(Event* pEvent);
625
627 void waitForEvent(WaitQueue::StackDiscardCleanup onStackDiscard = nullptr,
628 void* stackDiscardContext = nullptr);
629
634 bool waitForEventOrSignalInterruption(WaitQueue::StackDiscardCleanup onStackDiscard = nullptr,
635 void* stackDiscardContext = nullptr);
636
637#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
638 enum StateTransitionWindow {
639 StatePushBeforePublish,
640 StatePushAfterPublish,
641 StatePopAfterPublish,
642 };
643 enum ExternalLeaseReleasePhase {
644 ExternalLeaseFinalReleaseUnlocked,
645 ExternalLeaseBeforeWaiterWake,
646 };
647 using StateTransitionHook = void (*)(StateTransitionWindow window, Thread* thread,
648 size_t previousLevel, size_t nextLevel);
649 using JoinOperationHook = void (*)(Thread* target, Process* parent);
650 using ExternalLeaseReleaseHook = void (*)(Thread* target, ExternalLeaseReleasePhase phase);
651 using DeferredScopeLockHook = void (*)();
652 using SignalWaitPreEnrolmentHook = void (*)(Thread* target);
653
655 static void setStateTransitionHook(StateTransitionHook hook);
656
658 static void setJoinOperationHook(JoinOperationHook hook);
659
661 static void setExternalLeaseReleaseHookForHostedTest(Thread* target,
662 ExternalLeaseReleaseHook hook);
663
665 static void setSignalWaitPreEnrolmentHookForHostedTest(Thread* target,
666 SignalWaitPreEnrolmentHook hook);
667
669 bool isReapableForHostedTest();
670
672 bool wasStartPublishedForHostedTest();
673
675 bool waitUntilReapableForHostedTest();
676
681 bool runHostedPrequeuedEventRegression();
682
684 bool runHostedEventDeliveryLeaseRegression();
685
687 bool runHostedEventShutdownRegression();
688
690 bool runHostedStatePublicationRegression();
691
693 bool runHostedStateCleanupRegression();
694
696 bool runHostedExecStackOwnershipRegression();
697
699 void withDeferredScopeLockForTest(DeferredScopeLockHook hook);
700#endif
701
705 void inhibitEvent(size_t eventNumber, bool bInhibit);
706
708 uint64_t getSignalMask();
709
711 void setSignalMask(uint64_t mask);
712
714 uint64_t getSignalMaskForReturnFrame();
715
717 void commitSignalHandlerMask(uint64_t mask);
718
720 void restoreDeferredSignalMask(size_t stateLevel);
721
723 const SyscallState* getOriginalSyscallState() const {
724 return m_OriginalSyscallState;
725 }
726
727 void setOriginalSyscallState(const SyscallState* state) {
728 m_OriginalSyscallState = state;
729 if (state) {
730 __atomic_fetch_or(&m_UserReturnWorkPending, UserReturnOriginalSyscall, __ATOMIC_RELEASE);
731 } else {
732 __atomic_fetch_and(&m_UserReturnWorkPending, ~static_cast<size_t>(UserReturnOriginalSyscall),
733 __ATOMIC_RELEASE);
734 }
735 }
736
738 void setCurrentSignalDelivery(size_t signalNumber, size_t continuationEpoch);
739
741 bool getCurrentSignalDelivery(size_t& signalNumber, size_t& continuationEpoch);
742
744 void prepareSignalStateForExec();
745
747 bool hasTemporarySignalWaitInterruption();
748
750 bool hasActiveTemporarySignalMask();
751
753 bool retainTemporarySignalWaitInterruptionOrClear();
754
756 AlternateSignalStack() : base(0), size(0), enabled(false), inUse(false) {}
757
758 uintptr_t base;
759 size_t size;
760 bool enabled;
761 bool inUse;
762 };
763
764 AlternateSignalStack& getAlternateSignalStack() {
765 return m_AlternateSignalStack;
766 }
767
769 void cullEvent(Event* pEvent);
770
773 void cullEvent(size_t eventNumber);
774
776 void cullSignalEvent(size_t signalNumber);
777
782 bool transferProcessSignalsTo(Thread& target);
783
789 bool replaceSignalEvent(size_t signalNumber, Event* replacement, int processDirected = -1,
790 uint64_t rebindGeneration = 0);
791
793 bool hasSignalEvent(size_t signalNumber, int processDirected = -1);
794
795 bool acceptingEvents();
796 uint64_t pendingSignalMask(bool processOnly = false);
797 uint64_t pendingSignalOrder(size_t signal, bool processOnly = false);
798 Event::Delivery reservePendingSignal(uint64_t mask, bool processOnly = false,
799 uint64_t expectedSequence = ~uint64_t(0));
800 bool restorePendingSignal(Event::Delivery& delivery);
801 void cullSignalSource(const void* source);
802 void setSynchronousSignalMask(uint64_t mask);
803 uint64_t getSynchronousSignalMask();
804
805 bool hasEvents();
806
808 bool hasEvent(Event* pEvent);
809 bool hasEvent(size_t eventNumber);
810
811 void setPriority(size_t p) {
812 m_Priority = p;
813 }
814 size_t getPriority() {
815 return m_Priority;
816 }
817
819 void unexpectedExit();
820
822 uintptr_t getTlsBase();
823
829 void resetTlsBase();
830
831#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
832 enum TlsResetPhase {
833 TlsResetBeforeClear,
834 TlsResetCleared,
835 TlsResetRemapped,
836 };
837 using TlsResetHook = void (*)(Thread* thread, TlsResetPhase phase, uintptr_t base);
838
840 static void setTlsResetHookForHostedTest(Thread* target, TlsResetHook hook);
841#endif
842
848 void setTlsBase(uintptr_t base);
849
850#if X64 && !HOSTED
851 uintptr_t getUserGsBase() const {
852 return m_UserGsBase;
853 }
854 void setUserGsBase(uintptr_t base);
855 void saveUserGsBase();
856#endif
857
859 inline
860#if MULTIPROCESSOR
862#else
863 size_t
864#endif
866 return m_ProcId;
867 }
868
870 inline void setCpuId(
871#if MULTIPROCESSOR
873#else
874 size_t
875#endif
876 id) {
877 m_ProcId = id;
878 }
879
887 bool join();
888
895 bool joinForCompletion();
896
905 bool detach();
906
910 bool detached() const {
911 return m_bDetached;
912 }
913
920 static void threadExited() NORETURN;
921
923 bool eventsDeferred() const;
924
926 ExecutionContext executionContext() const;
927
929 class PerProcessorScheduler* getScheduler() const {
930 return __atomic_load_n(&m_pScheduler, __ATOMIC_ACQUIRE);
931 }
932
933 const String& getName() const {
934 return m_Name;
935 }
936
937 void setName(const String& name) {
938 m_Name = name;
939 }
940
941 template <size_t N>
942 void setName(const char (&name)[N]) {
943 m_Name.assign(name, N);
944 }
945
946#if HOSTED
948 size_t enterHostedSignalHandler();
949
951 void leaveHostedSignalHandler(size_t stateLevel);
952
953 size_t getHostedSignalDepth() const {
954 const size_t level = __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
955 return __atomic_load_n(&m_StateLevels[level].m_HostedSignalDepth, __ATOMIC_ACQUIRE);
956 }
957#endif
958
959 protected:
961 void setScheduler(class PerProcessorScheduler* pScheduler);
962
963 void deferEvents();
964 void resumeEvents();
965 void deferTermination();
966 void resumeTermination();
967 void markUserReturnWorkFlag(UserReturnWorkFlag flag) {
968 __atomic_fetch_or(&m_UserReturnWorkPending, static_cast<size_t>(flag), __ATOMIC_RELEASE);
969 }
970 void clearUserReturnWorkFlag(UserReturnWorkFlag flag) {
971 __atomic_fetch_and(&m_UserReturnWorkPending, ~static_cast<size_t>(flag), __ATOMIC_RELEASE);
972 }
973 void markUserReturnWorkPending() {
974 markUserReturnWorkFlag(UserReturnExternalWork);
975 }
976 void registerDeferredScope(DeferredScopeRecord& record, bool termination, bool events);
977 void armStateCleanup(DeferredScopeRecord& record, DeferredScopeRecord::Cleanup cleanup,
978 void* context);
979 void unregisterDeferredScope(DeferredScopeRecord& record);
980 void disarmStateCleanup(DeferredScopeRecord& record);
981 void unregisterTerminationDeferral(DeferredScopeRecord& record);
982 void moveTerminationDeferral(DeferredScopeRecord& from, DeferredScopeRecord& to);
983 void retireDeferredScopes(bool allStateLevels, size_t stateLevel = 0);
984 size_t stateCleanupCheckpoint();
985 void retireDeferredScopesAfter(size_t checkpoint);
986 void retireDeferredScopesMatching(bool allStateLevels, size_t stateLevel,
987 bool newerThanCheckpoint, size_t checkpoint);
988 void armAtomicStateCleanup(AtomicStateCleanupRecord& record,
989 AtomicStateCleanupRecord::Cleanup cleanup, void* context);
990 void disarmAtomicStateCleanup(AtomicStateCleanupRecord& record);
991
992 private:
993 void publishDeferredScope(DeferredScopeRecord& record, bool termination, bool events,
994 DeferredScopeRecord::Cleanup cleanup, void* context);
995 void unpublishDeferredScope(DeferredScopeRecord& record, bool deferrals);
996 void registerFreshTerminationDeferral(DeferredScopeRecord& record,
997 DeferredScopeRecord::Cleanup cleanup = nullptr,
998 void* context = nullptr);
999
1004
1006 void publishTimeAccounting(CpuTimeMode mode, Time::Timestamp elapsed);
1007
1008 void initialisePlacement(const ThreadPlacement* placement);
1009 void publishReadyNotification();
1010
1012 void cleanStateLevel(size_t level);
1013
1014 size_t beginTemporarySignalMask(uint64_t signalMask);
1015 bool finishTemporarySignalMask(size_t stateLevel, bool deferForUserReturn = true);
1016 bool waitForEventInternal(bool stopOnSignalInterruption,
1017 WaitQueue::StackDiscardCleanup onStackDiscard,
1018 void* stackDiscardContext);
1019
1020 enum class EventSelection {
1021 AnyDeliverable,
1022 WithoutExactUserReturn,
1023 KernelDeliverable,
1024 StoppedProcessKernel,
1025 };
1026
1028 bool eventNeedsUserReturnFrameUnlocked(Event* event) const;
1029 bool eventIsDeliverableUnlocked(Event* event,
1030 EventSelection selection = EventSelection::AnyDeliverable);
1031
1033 bool hasEventsUnlocked(EventSelection selection = EventSelection::AnyDeliverable);
1034 bool hasDeliverableEventsUnlocked(EventSelection selection = EventSelection::AnyDeliverable);
1035
1037 void markDeferredUserReturnSignalInterruption();
1038
1040 void wakeForDeliverableEvents();
1041
1043 MUST_USE_RESULT Event::Delivery getNextEvent(
1044 EventSelection selection = EventSelection::AnyDeliverable);
1045
1047 void setStatus(Status s);
1048 void setStatusUnlocked(Status s);
1049
1054 bool markReapable();
1055
1057 bool joinInternal(bool completion);
1058
1060 Thread* target;
1061 Process* parent;
1062 bool claimed;
1063 };
1064
1066 static void discardJoin(void* context);
1067
1069 bool beginExternalLease();
1070
1072 void endExternalLease();
1073
1075 void closeExternalLeaseAdmission();
1076
1078 void closeExternalLeaseAdmissionAndDrain();
1079
1081 bool interruptWaitUnlocked(WaitQueue::WakeReason reason, PerProcessorScheduler*& readyScheduler);
1082 bool hasActiveWaitUnlocked() const;
1083 bool hasActiveWaitAtAnyLevel() const;
1084 bool activeWaitPendingUnlocked() const;
1085
1087 void unlinkWaitsForStackDiscard();
1088
1094 void markTerminalWaitCancelledBeforeBlockUnlocked(size_t level);
1095 bool consumeTerminalWaitCancelledBeforeBlockUnlocked();
1096 void clearTerminalWaitCancelledBeforeBlockUnlocked(size_t level);
1097
1099 struct StateLevel {
1100 StateLevel();
1101 ~StateLevel();
1102
1103 StateLevel(const StateLevel& s);
1104 StateLevel& operator=(const StateLevel& s);
1105
1107 SchedulerState* m_State;
1108 UserReturnFrame* m_UserReturnFrame = nullptr;
1109
1112
1113 VirtualAddressSpace::Stack* m_pUserStack;
1114
1120
1127
1130
1133 bool m_TemporarySignalMaskActive;
1134 bool m_TemporarySignalWaitInterrupted;
1135 bool m_DeferredSignalMaskRestore;
1136
1139 size_t m_DispatchedSignalContinuationEpoch;
1140
1143
1145 size_t m_Errno;
1146 InterruptionReason m_InterruptionReason;
1147
1150
1153
1156
1163
1164#if HOSTED
1166 size_t m_HostedSignalDepth;
1167#endif
1168
1171 };
1172
1175
1177 size_t m_nStateLevel = 0;
1178
1180 Process* m_pParent = nullptr;
1181 // VFS uses task-local filesystem IDs even when the POSIX identity is shared.
1182 uint32_t m_FilesystemUid = 0, m_FilesystemGid = 0;
1183 bool m_FilesystemIdsValid = false;
1184 const FilesystemCredentials* m_FilesystemOverride = nullptr;
1185 SecurityStateRef m_SecurityState;
1186 bool m_HasSecurityState = false;
1187
1190
1193
1195 Time::Timestamp m_UserTime = 0;
1196 Time::Timestamp m_KernelTime = 0;
1197
1199 size_t m_CurrentTimeAccountingMode = static_cast<size_t>(CpuTimeMode::Kernel);
1200
1201#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1202 size_t m_ActiveSyscallTimingSlot = NoSyscallTimingSlot;
1203#endif
1204
1208 void* m_pAllocatedStack = nullptr;
1209
1211 size_t m_Id = 0;
1212 size_t m_TaskId = 0;
1213 SharedPointer<UserspacePid> m_UserspacePid;
1214
1216 uintptr_t m_DebugStateAddress = 0;
1217
1219 size_t m_DebugStateGeneration = 0;
1220
1221 class PerProcessorScheduler* m_pScheduler = nullptr;
1222
1223 ThreadPlacement m_Placement;
1224 CpuAffinityMask m_RequestedAffinity;
1225 WaitQueue m_AffinityWaiters;
1226 uint64_t m_AffinityGeneration = 0;
1227 uint64_t m_AffinityCompleted = 0;
1228 bool m_AffinityPending = false;
1229 bool m_AffinityGatePending = false;
1230 bool m_AffinityWorkQueued = false;
1231 size_t m_AffinityReturnPending = 0;
1232 bool m_SignalFramesRequired = false;
1233 bool m_UserReturnSignalParked = false;
1234 size_t m_UserReturnWorkPending = 0;
1235 Thread* m_AffinityNext = nullptr;
1236 bool m_HasSchedulerContext = false;
1237 bool m_ReadyPublicationPending = false;
1238
1240 size_t m_Priority = DEFAULT_PRIORITY;
1241
1243 Thread* m_pReadyPrevious = nullptr;
1244 Thread* m_pReadyNext = nullptr;
1245 size_t m_ReadyQueuePriority = MAX_PRIORITIES;
1246 bool m_bReadyQueued = false;
1247
1249 void* m_pTlsBase = nullptr;
1250#if X64 && !HOSTED
1251 uintptr_t m_UserGsBase = 0;
1252#endif
1253
1254#if MULTIPROCESSOR
1256#else
1257 size_t
1258#endif
1259 m_ProcId = 0;
1260
1263
1266
1269
1272
1274 size_t m_nExternalLeases = 0;
1275
1277 bool m_bExternalLeaseAdmissionClosed = false;
1278
1285 bool m_bExternalLeaseReleaseInProgress = false;
1286
1289
1292
1295
1297 size_t m_EventSendersInFlight = 0;
1298
1299 StateLevel m_StateLevels[MAX_NESTED_EVENTS];
1300
1303
1304 const SyscallState* m_OriginalSyscallState = nullptr;
1305 void* m_SyscallDispatchContext = nullptr;
1307 size_t m_ActiveSyscalls[serviceEnd] = {};
1308
1310 volatile Status m_Status = Ready;
1311 ExecutionPersonality m_ExecutionPersonality;
1312
1314 bool m_ExitToIdle = false;
1315
1317 int m_ExitCode = 0;
1318
1321 DebugState m_DebugState = None;
1322
1323 UnwindType m_UnwindState = Continue;
1324
1326 uint64_t m_DeferredProcessExitRequest = 0;
1327 uint64_t m_SynchronousSignalMask = 0;
1328
1330 size_t m_DeferredSubsystemExceptionState = 0;
1331 size_t m_DeferredSubsystemExceptionType = 0;
1332 uintptr_t m_DeferredSubsystemExceptionFaultAddress = 0;
1333 uintptr_t m_DeferredSubsystemExceptionErrorCode = 0;
1334
1336 bool m_bTlsBaseOverride = false;
1337
1339 bool m_bShutdown = false;
1340
1342 bool m_bSubsystemExitNotified = false;
1343
1345 uintptr_t m_ClearChildTid = 0;
1346
1348 uintptr_t m_RobustList = 0;
1349 size_t m_RobustListOwnerId = 0;
1350
1352 bool m_bStartRequested = false;
1353
1355 bool m_bDetached = false;
1356
1358 bool m_bJoinClaimed = false;
1359
1361 bool m_bDetachedRetirementClaimed = false;
1362
1364 bool m_bThreadExitRequested = false;
1365
1367 bool m_bExitStarted = false;
1368
1370 bool m_bReapable = false;
1371
1373 bool m_bProcessExitOwned = false;
1374
1376 bool m_bProcessExitParticipant = false;
1377
1379 size_t m_EventDeferralDepth = 0;
1380
1381#if PEDIGREE_LATENCY_ACCOUNTING
1383 Time::Timestamp m_EventDeferralStarted = 0;
1384#endif
1385
1387 size_t m_TerminationDeferralDepth = 0;
1388
1390 DeferredScopeRecord* m_pDeferredScopes[MAX_NESTED_EVENTS] = {};
1391 size_t m_NextStateCleanupSequence = 0;
1392
1393#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1394 Spinlock m_DeferredScopeRegressionLock;
1395#endif
1396};
1397
1398#endif
Definition Event.h:49
Definition List.h:61
This class manages how processes and threads are scheduled across processors.
Definition Scheduler.h:50
ThreadTimeAccounting m_TimeAccounting
Definition Thread.h:1192
void setErrno(size_t err)
Definition Thread.h:482
WaitQueue m_JoinWaiters
Definition Thread.h:1265
WaitQueue m_EventWaiters
Definition Thread.h:1288
Thread(const Thread &)
AlternateSignalStack m_AlternateSignalStack
Definition Thread.h:1302
UnwindType
Definition Thread.h:516
@ Exit
Exit the owning process at the next safe boundary.
Definition Thread.h:518
void setDebugState(DebugState state, uintptr_t address)
Definition Thread.h:593
DebugState
Definition Thread.h:177
size_t getErrno()
Definition Thread.h:477
Time::Timestamp getUserTime() const
Definition Thread.h:412
WaitQueue m_ExternalLeaseWaiters
Definition Thread.h:1271
const SyscallState * getOriginalSyscallState() const
Definition Thread.h:723
Status getStatus() const
Definition Thread.h:433
UnwindType getUnwindState()
Definition Thread.h:535
DeferredThreadReapNode m_DeferredReapNode
Definition Thread.h:1189
uintptr_t takeClearChildTid()
Definition Thread.h:348
bool detached() const
Definition Thread.h:910
Spinlock m_Lock
Definition Thread.h:1262
ALWAYS_INLINE void transitionTimeAtInterruptReturn(CpuTimeMode from, CpuTimeMode to)
Definition Thread.h:373
DebugState getDebugState(uintptr_t &address)
Definition Thread.h:574
Process * getParent() const
Definition Thread.h:340
size_t getId()
Definition Thread.h:465
void setCpuId(size_t id)
Definition Thread.h:870
Spinlock m_ExternalLeaseLock
Definition Thread.h:1268
size_t getCpuId()
Definition Thread.h:865
int getExitCode()
Definition Thread.h:454
Spinlock & getLock()
Definition Thread.h:613
bool isTerminationDeferred() const
Definition Thread.h:569
Thread & operator=(const Thread &)
size_t getStateLevel() const
Definition Thread.h:316
WaitQueue m_EventSenderDrainWaiters
Definition Thread.h:1291
List< Event * > m_EventQueue
Definition Thread.h:1294
bool wasInterrupted()
Definition Thread.h:493
String m_Name
Definition Thread.h:1174
size_t ProcessorId
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