114 static void restore(
void* context);
123 bool tryRequireSignalFrames();
124 void clearSignalFrameRequirement();
125 void setUserReturnSignalParked(
bool parked);
127 enum UserReturnWorkFlag :
size_t {
128 UserReturnExternalWork = 1,
129 UserReturnEventsDeferred = 1 << 1,
130 UserReturnSignalFrames = 1 << 3,
131 UserReturnDeferredException = 1 << 4,
132 UserReturnOriginalSyscall = 1 << 5,
135 bool canSkipUserReturnWork();
136 bool clearUserReturnWorkIfIdle();
137 bool userReturnWorkPending()
const {
138 return __atomic_load_n(&m_UserReturnWorkPending, __ATOMIC_ACQUIRE) != 0 ||
139 isTerminationDeferred();
141 bool requiresSignalFrames()
const {
142 return __atomic_load_n(&m_SignalFramesRequired, __ATOMIC_ACQUIRE);
157 static void discard(
void* context);
187 typedef int (*ThreadStartFunc)(
void*);
207 Thread(
Process* pParent, ThreadStartFunc pStartFunction,
void* pParam,
void* pStack = 0,
208 bool semiUser =
false,
bool bDontPickCore =
false,
bool delayedStart =
false,
218 Thread(
Process* pParent, SyscallState& state,
bool delayedStart =
false,
225 AffinityResult requestAffinity(
const CpuAffinityMask& mask, uint64_t& generation);
227 AffinityResult waitAffinity(uint64_t generation);
233 AffinityResult completeAffinityAtSafePoint(
bool* waited =
nullptr);
234 bool affinityWorkPending()
const {
235 return __atomic_load_n(&m_AffinityReturnPending, __ATOMIC_ACQUIRE) != 0;
237#if PEDIGREE_AFFINITY_TESTS
238 using AffinityCommitHook = void (*)(
Thread*);
239 static void setAffinityCommitHookForTest(
Thread* target, AffinityCommitHook hook);
260 void notifySubsystemExit();
262 void forceToStartupProcessor();
266 SchedulerState& state();
272 SchedulerState* pushState();
278 void popState(
bool clean =
true);
281 void abandonCurrentState(
bool clean =
false);
284 void abandonAllStates();
295 void discardUserStackMetadataForExec();
302 return __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
305 void* getSyscallDispatchContext()
const {
306 return m_SyscallDispatchContext;
308 void setSyscallDispatchContext(
void* context) {
309 m_SyscallDispatchContext = context;
313 void allocateStackAtLevel(
size_t stateLevel);
316 void setKernelStack();
322 void pokeState(
size_t stateLevel, SchedulerState& state);
330 void setClearChildTid(uintptr_t address);
334 return __atomic_exchange_n(&m_ClearChildTid,
static_cast<uintptr_t
>(0), __ATOMIC_ACQ_REL);
337 void setRobustList(uintptr_t address,
size_t ownerId);
339 uintptr_t getRobustList()
const {
340 return __atomic_load_n(&m_RobustList, __ATOMIC_ACQUIRE);
343 uintptr_t takeRobustList(
size_t& ownerId);
346 void recordTime(CpuTimeMode mode);
349 void trackTime(CpuTimeMode mode);
352 void transitionTime(CpuTimeMode from, CpuTimeMode to,
bool interruptsAlreadyDisabled =
false);
359 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
364 const auto sample = Time::sampleCpuTime();
365 const Time::Timestamp elapsed =
366 m_TimeAccounting.elapsedAtInterruptDisabled(from, sample.timestamp, sample.processor);
367 m_TimeAccounting.recordAtInterruptDisabled(to, sample.timestamp, sample.processor);
368 __atomic_store_n(&m_CurrentTimeAccountingMode,
static_cast<size_t>(to), __ATOMIC_RELEASE);
370 publishTimeAccounting(from, elapsed);
374 __atomic_store_n(&m_CurrentTimeAccountingMode,
static_cast<size_t>(to), __ATOMIC_RELEASE);
379 CpuTimeMode currentTimeAccountingMode()
const;
382 void accountTimerTick(Time::Timestamp delta,
bool kernelMode);
384#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
385 static constexpr size_t NoSyscallTimingSlot = ~static_cast<size_t>(0);
387 size_t installSyscallTimingSlot(
size_t slot) {
388 return __atomic_exchange_n(&m_ActiveSyscallTimingSlot, slot, __ATOMIC_ACQ_REL);
391 void restoreSyscallTimingSlot(
size_t slot) {
392 __atomic_store_n(&m_ActiveSyscallTimingSlot, slot, __ATOMIC_RELEASE);
398 return __atomic_load_n(&m_UserTime, __ATOMIC_ACQUIRE);
400 Time::Timestamp getKernelTime()
const {
401 return __atomic_load_n(&m_KernelTime, __ATOMIC_ACQUIRE);
404#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
406 void publishTimeAccountingForHostedTest(Time::Timestamp user, Time::Timestamp system);
414 return m_ExecutionPersonality;
436 bool startDetached();
444 void* getKernelStack();
447 void* getKernelStackBase(
size_t* size)
const;
456 return __atomic_load_n(&m_TaskId, __ATOMIC_ACQUIRE);
461 return m_StateLevels[m_nStateLevel].m_Errno;
466 m_StateLevels[m_nStateLevel].m_Errno = err;
469 enum InterruptionReason {
471 InterruptedByTimeout,
477 return getInterruptionReason() != NotInterrupted;
480 void clearInterruption() {
481 m_StateLevels[m_nStateLevel].m_InterruptionReason = NotInterrupted;
484 InterruptionReason getInterruptionReason() {
485 return m_StateLevels[m_nStateLevel].m_InterruptionReason;
488 void setInterruptionReason(InterruptionReason reason) {
489 m_StateLevels[m_nStateLevel].m_InterruptionReason = reason;
493 void markTimeoutInterruptedWait();
496 void markSignalInterruptedWait();
519 return __atomic_load_n(&m_UnwindState, __ATOMIC_ACQUIRE);
522 void setUnwindState(UnwindType ut);
525 void deferProcessExit(
int code);
528 void deferSignalExit(
int signal);
542 bool deferSubsystemException(
size_t type, uintptr_t faultAddress, uintptr_t errorCode);
544 bool hasDeferredSubsystemException()
const {
545 return __atomic_load_n(&m_DeferredSubsystemExceptionState, __ATOMIC_ACQUIRE) != 0;
549 bool takeDeferredSubsystemException(
size_t& type, uintptr_t& faultAddress, uintptr_t& errorCode);
553 return __atomic_load_n(&m_TerminationDeferralDepth, __ATOMIC_ACQUIRE) != 0;
558 for (
size_t attempt = 0; attempt < 2; ++attempt) {
559 const size_t generation = __atomic_load_n(&m_DebugStateGeneration, __ATOMIC_ACQUIRE);
560 if (generation & 1) {
564 const DebugState state = __atomic_load_n(&m_DebugState, __ATOMIC_RELAXED);
565 const uintptr_t observedAddress = __atomic_load_n(&m_DebugStateAddress, __ATOMIC_RELAXED);
566 if (generation == __atomic_load_n(&m_DebugStateGeneration, __ATOMIC_ACQUIRE)) {
567 address = observedAddress;
577 __atomic_add_fetch(&m_DebugStateGeneration,
static_cast<size_t>(1), __ATOMIC_ACQ_REL);
578 __atomic_store_n(&m_DebugStateAddress, address, __ATOMIC_RELAXED);
579 __atomic_store_n(&m_DebugState, state, __ATOMIC_RELAXED);
580 __atomic_add_fetch(&m_DebugStateGeneration,
static_cast<size_t>(1), __ATOMIC_RELEASE);
585 const void* channelOwner;
586 uintptr_t channelValue;
587 WaitQueue::WakeReason reason;
607 bool sendEvent(
Event* pEvent);
610 void waitForEvent(WaitQueue::StackDiscardCleanup onStackDiscard =
nullptr,
611 void* stackDiscardContext =
nullptr);
617 bool waitForEventOrSignalInterruption(WaitQueue::StackDiscardCleanup onStackDiscard =
nullptr,
618 void* stackDiscardContext =
nullptr);
620#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
621 enum StateTransitionWindow {
622 StatePushBeforePublish,
623 StatePushAfterPublish,
624 StatePopAfterPublish,
626 enum ExternalLeaseReleasePhase {
627 ExternalLeaseFinalReleaseUnlocked,
628 ExternalLeaseBeforeWaiterWake,
630 using StateTransitionHook = void (*)(StateTransitionWindow window,
Thread* thread,
631 size_t previousLevel,
size_t nextLevel);
632 using JoinOperationHook = void (*)(
Thread* target,
Process* parent);
633 using ExternalLeaseReleaseHook = void (*)(
Thread* target, ExternalLeaseReleasePhase phase);
634 using DeferredScopeLockHook = void (*)();
635 using SignalWaitPreEnrolmentHook = void (*)(
Thread* target);
638 static void setStateTransitionHook(StateTransitionHook hook);
641 static void setJoinOperationHook(JoinOperationHook hook);
644 static void setExternalLeaseReleaseHookForHostedTest(
Thread* target,
645 ExternalLeaseReleaseHook hook);
648 static void setSignalWaitPreEnrolmentHookForHostedTest(
Thread* target,
649 SignalWaitPreEnrolmentHook hook);
652 bool isReapableForHostedTest();
655 bool wasStartPublishedForHostedTest();
658 bool waitUntilReapableForHostedTest();
664 bool runHostedPrequeuedEventRegression();
667 bool runHostedEventDeliveryLeaseRegression();
670 bool runHostedEventShutdownRegression();
673 bool runHostedStatePublicationRegression();
676 bool runHostedStateCleanupRegression();
679 bool runHostedExecStackOwnershipRegression();
682 void withDeferredScopeLockForTest(DeferredScopeLockHook hook);
688 void inhibitEvent(
size_t eventNumber,
bool bInhibit);
691 uint64_t getSignalMask();
694 void setSignalMask(uint64_t mask);
697 uint64_t getSignalMaskForReturnFrame();
700 void commitSignalHandlerMask(uint64_t mask);
703 void restoreDeferredSignalMask(
size_t stateLevel);
707 return m_OriginalSyscallState;
710 void setOriginalSyscallState(
const SyscallState* state) {
711 m_OriginalSyscallState = state;
713 __atomic_fetch_or(&m_UserReturnWorkPending, UserReturnOriginalSyscall, __ATOMIC_RELEASE);
715 __atomic_fetch_and(&m_UserReturnWorkPending, ~
static_cast<size_t>(UserReturnOriginalSyscall),
721 void setCurrentSignalDelivery(
size_t signalNumber,
size_t continuationEpoch);
724 bool getCurrentSignalDelivery(
size_t& signalNumber,
size_t& continuationEpoch);
727 void prepareSignalStateForExec();
730 bool hasTemporarySignalWaitInterruption();
733 bool hasActiveTemporarySignalMask();
736 bool retainTemporarySignalWaitInterruptionOrClear();
748 return m_AlternateSignalStack;
752 void cullEvent(
Event* pEvent);
756 void cullEvent(
size_t eventNumber);
759 void cullSignalEvent(
size_t signalNumber);
765 bool transferProcessSignalsTo(
Thread& target);
772 bool replaceSignalEvent(
size_t signalNumber,
Event* replacement,
int processDirected = -1,
773 uint64_t rebindGeneration = 0);
776 bool hasSignalEvent(
size_t signalNumber,
int processDirected = -1);
778 bool acceptingEvents();
779 uint64_t pendingSignalMask(
bool processOnly =
false);
780 uint64_t pendingSignalOrder(
size_t signal,
bool processOnly =
false);
781 Event::Delivery reservePendingSignal(uint64_t mask,
bool processOnly =
false,
782 uint64_t expectedSequence = ~uint64_t(0));
784 void cullSignalSource(
const void* source);
785 void setSynchronousSignalMask(uint64_t mask);
786 uint64_t getSynchronousSignalMask();
791 bool hasEvent(
Event* pEvent);
792 bool hasEvent(
size_t eventNumber);
794 void setPriority(
size_t p) {
797 size_t getPriority() {
802 void unexpectedExit();
805 uintptr_t getTlsBase();
814#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
820 using TlsResetHook = void (*)(
Thread* thread, TlsResetPhase phase, uintptr_t base);
823 static void setTlsResetHookForHostedTest(
Thread* target, TlsResetHook hook);
831 void setTlsBase(uintptr_t base);
834 uintptr_t getUserGsBase()
const {
837 void setUserGsBase(uintptr_t base);
838 void saveUserGsBase();
878 bool joinForCompletion();
903 static void threadExited()
NORETURN;
906 bool eventsDeferred() const;
909 ExecutionContext executionContext() const;
913 return __atomic_load_n(&m_pScheduler, __ATOMIC_ACQUIRE);
916 const String& getName()
const {
920 void setName(
const String& name) {
925 void setName(
const char (&name)[N]) {
926 m_Name.assign(name, N);
931 size_t enterHostedSignalHandler();
934 void leaveHostedSignalHandler(
size_t stateLevel);
936 size_t getHostedSignalDepth()
const {
937 const size_t level = __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
938 return __atomic_load_n(&m_StateLevels[level].m_HostedSignalDepth, __ATOMIC_ACQUIRE);
948 void deferTermination();
949 void resumeTermination();
950 void markUserReturnWorkFlag(UserReturnWorkFlag flag) {
951 __atomic_fetch_or(&m_UserReturnWorkPending,
static_cast<size_t>(flag), __ATOMIC_RELEASE);
953 void clearUserReturnWorkFlag(UserReturnWorkFlag flag) {
954 __atomic_fetch_and(&m_UserReturnWorkPending, ~
static_cast<size_t>(flag), __ATOMIC_RELEASE);
956 void markUserReturnWorkPending() {
957 markUserReturnWorkFlag(UserReturnExternalWork);
966 void retireDeferredScopes(
bool allStateLevels,
size_t stateLevel = 0);
967 size_t stateCleanupCheckpoint();
968 void retireDeferredScopesAfter(
size_t checkpoint);
969 void retireDeferredScopesMatching(
bool allStateLevels,
size_t stateLevel,
970 bool newerThanCheckpoint,
size_t checkpoint);
972 AtomicStateCleanupRecord::Cleanup cleanup,
void* context);
977 DeferredScopeRecord::Cleanup cleanup =
nullptr,
978 void* context =
nullptr);
986 void publishTimeAccounting(CpuTimeMode mode, Time::Timestamp elapsed);
989 void publishReadyNotification();
992 void cleanStateLevel(
size_t level);
994 size_t beginTemporarySignalMask(uint64_t signalMask);
995 bool finishTemporarySignalMask(
size_t stateLevel,
bool deferForUserReturn =
true);
996 bool waitForEventInternal(
bool stopOnSignalInterruption,
997 WaitQueue::StackDiscardCleanup onStackDiscard,
998 void* stackDiscardContext);
1000 enum class EventSelection {
1002 WithoutExactUserReturn,
1004 StoppedProcessKernel,
1008 bool eventNeedsUserReturnFrameUnlocked(
Event* event)
const;
1009 bool eventIsDeliverableUnlocked(
Event* event,
1010 EventSelection selection = EventSelection::AnyDeliverable);
1013 bool hasEventsUnlocked(EventSelection selection = EventSelection::AnyDeliverable);
1014 bool hasDeliverableEventsUnlocked(EventSelection selection = EventSelection::AnyDeliverable);
1017 void markDeferredUserReturnSignalInterruption();
1020 void wakeForDeliverableEvents();
1024 EventSelection selection = EventSelection::AnyDeliverable);
1027 void setStatus(Status s);
1028 void setStatusUnlocked(Status s);
1034 bool markReapable();
1037 bool joinInternal(
bool completion);
1046 static void discardJoin(
void* context);
1049 bool beginExternalLease();
1052 void endExternalLease();
1055 void closeExternalLeaseAdmission();
1058 void closeExternalLeaseAdmissionAndDrain();
1062 bool hasActiveWaitUnlocked()
const;
1063 bool hasActiveWaitAtAnyLevel()
const;
1064 bool activeWaitPendingUnlocked()
const;
1067 void unlinkWaitsForStackDiscard();
1074 void markTerminalWaitCancelledBeforeBlockUnlocked(
size_t level);
1075 bool consumeTerminalWaitCancelledBeforeBlockUnlocked();
1076 void clearTerminalWaitCancelledBeforeBlockUnlocked(
size_t level);
1113 bool m_TemporarySignalMaskActive;
1114 bool m_TemporarySignalWaitInterrupted;
1115 bool m_DeferredSignalMaskRestore;
1119 size_t m_DispatchedSignalContinuationEpoch;
1126 InterruptionReason m_InterruptionReason;
1146 size_t m_HostedSignalDepth;
1157 size_t m_nStateLevel = 0;
1162 uint32_t m_FilesystemUid = 0, m_FilesystemGid = 0;
1163 bool m_FilesystemIdsValid =
false;
1173 Time::Timestamp m_UserTime = 0;
1174 Time::Timestamp m_KernelTime = 0;
1177 size_t m_CurrentTimeAccountingMode =
static_cast<size_t>(CpuTimeMode::Kernel);
1179#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1180 size_t m_ActiveSyscallTimingSlot = NoSyscallTimingSlot;
1186 void* m_pAllocatedStack =
nullptr;
1190 size_t m_TaskId = 0;
1193 uintptr_t m_DebugStateAddress = 0;
1196 size_t m_DebugStateGeneration = 0;
1203 uint64_t m_AffinityGeneration = 0;
1204 uint64_t m_AffinityCompleted = 0;
1205 bool m_AffinityPending =
false;
1206 bool m_AffinityGatePending =
false;
1207 bool m_AffinityWorkQueued =
false;
1208 size_t m_AffinityReturnPending = 0;
1209 bool m_SignalFramesRequired =
false;
1210 bool m_UserReturnSignalParked =
false;
1211 size_t m_UserReturnWorkPending = 0;
1212 Thread* m_AffinityNext =
nullptr;
1213 bool m_HasSchedulerContext =
false;
1214 bool m_ReadyPublicationPending =
false;
1217 size_t m_Priority = DEFAULT_PRIORITY;
1221 Thread* m_pReadyNext =
nullptr;
1222 size_t m_ReadyQueuePriority = MAX_PRIORITIES;
1223 bool m_bReadyQueued =
false;
1226 void* m_pTlsBase =
nullptr;
1228 uintptr_t m_UserGsBase = 0;
1251 size_t m_nExternalLeases = 0;
1254 bool m_bExternalLeaseAdmissionClosed =
false;
1262 bool m_bExternalLeaseReleaseInProgress =
false;
1274 size_t m_EventSendersInFlight = 0;
1281 const SyscallState* m_OriginalSyscallState =
nullptr;
1282 void* m_SyscallDispatchContext =
nullptr;
1284 size_t m_ActiveSyscalls[serviceEnd] = {};
1291 bool m_ExitToIdle =
false;
1303 uint64_t m_DeferredProcessExitRequest = 0;
1304 uint64_t m_SynchronousSignalMask = 0;
1307 size_t m_DeferredSubsystemExceptionState = 0;
1308 size_t m_DeferredSubsystemExceptionType = 0;
1309 uintptr_t m_DeferredSubsystemExceptionFaultAddress = 0;
1310 uintptr_t m_DeferredSubsystemExceptionErrorCode = 0;
1313 bool m_bTlsBaseOverride =
false;
1316 bool m_bShutdown =
false;
1319 bool m_bSubsystemExitNotified =
false;
1322 uintptr_t m_ClearChildTid = 0;
1325 uintptr_t m_RobustList = 0;
1326 size_t m_RobustListOwnerId = 0;
1329 bool m_bStartRequested =
false;
1332 bool m_bDetached =
false;
1335 bool m_bJoinClaimed =
false;
1338 bool m_bDetachedRetirementClaimed =
false;
1341 bool m_bThreadExitRequested =
false;
1344 bool m_bExitStarted =
false;
1347 bool m_bReapable =
false;
1350 bool m_bProcessExitOwned =
false;
1353 bool m_bProcessExitParticipant =
false;
1356 size_t m_EventDeferralDepth = 0;
1358#if PEDIGREE_LATENCY_ACCOUNTING
1360 Time::Timestamp m_EventDeferralStarted = 0;
1364 size_t m_TerminationDeferralDepth = 0;
1368 size_t m_NextStateCleanupSequence = 0;
1370#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1371 Spinlock m_DeferredScopeRegressionLock;