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;
52class SyscallManager;
57class RoundRobin;
60class UserReturnFrame;
61
63#define THREAD_TLS_SIZE PAGE_SIZE
64
75class EXPORTED_PUBLIC Thread {
76 friend class PerProcessorScheduler;
77 friend class Scheduler;
78 friend class PageFaultHandler;
79 friend class Process;
80 friend class WaitQueue;
81 friend class Uninterruptible;
82 friend class TerminationDeferral;
83 friend class SyscallManager;
84 friend class IrqHandlerRegistry;
85 friend class TimerHandlerRegistry;
86 friend class HostedInterruptManager;
87 friend class RoundRobin;
88 friend class ExecutionContextGuard;
89 friend class RequestQueueCallbackScope;
91
92 public:
93 class EXPORTED_PUBLIC StackDiscardScope {
94 public:
95 StackDiscardScope(DeferredScopeRecord::Cleanup cleanup, void* context);
97
98 void disarm();
99
100 private:
101 NOT_COPYABLE_OR_ASSIGNABLE(StackDiscardScope);
102
103 Thread* m_pThread;
104 DeferredScopeRecord m_Record;
105 };
106
107 class EXPORTED_PUBLIC UserReturnFrameScope {
108 public:
111
112 private:
113 NOT_COPYABLE_OR_ASSIGNABLE(UserReturnFrameScope);
114 static void restore(void* context);
115 Thread* m_Owner;
116 size_t m_StateLevel;
117 UserReturnFrame* m_Frame;
118 UserReturnFrame* m_Previous;
119 DeferredScopeRecord m_Record;
120 };
121
122 UserReturnFrame* currentUserReturnFrame() const;
123 bool tryRequireSignalFrames();
124 void clearSignalFrameRequirement();
125 void setUserReturnSignalParked(bool parked);
126
127 enum UserReturnWorkFlag : size_t {
128 UserReturnExternalWork = 1,
129 UserReturnEventsDeferred = 1 << 1,
130 UserReturnSignalFrames = 1 << 3,
131 UserReturnDeferredException = 1 << 4,
132 UserReturnOriginalSyscall = 1 << 5,
133 };
134
135 bool canSkipUserReturnWork();
136 bool clearUserReturnWorkIfIdle();
137 bool userReturnWorkPending() const {
138 return __atomic_load_n(&m_UserReturnWorkPending, __ATOMIC_ACQUIRE) != 0 ||
139 isTerminationDeferred();
140 }
141 bool requiresSignalFrames() const {
142 return __atomic_load_n(&m_SignalFramesRequired, __ATOMIC_ACQUIRE);
143 }
144
146 class EXPORTED_PUBLIC TemporarySignalMask {
147 public:
148 TemporarySignalMask(Thread& thread, uint64_t signalMask);
150
152 bool finish();
153
154 private:
155 NOT_COPYABLE_OR_ASSIGNABLE(TemporarySignalMask);
156
157 static void discard(void* context);
158
159 Thread* m_pThread;
160 size_t m_StateLevel;
161 DeferredScopeRecord m_Record;
162 };
163
165 enum Status {
166 Created,
167 Ready,
168 Running,
169 Sleeping,
170 Zombie,
171 AwaitingJoin,
172 };
173
176 None,
177 SemWait,
178 CondWait,
179 Joining,
180 FutexWait,
181 EventWait,
182 ProcessWait,
183 CallbackDrain
184 };
185
187 typedef int (*ThreadStartFunc)(void*);
188
207 Thread(Process* pParent, ThreadStartFunc pStartFunction, void* pParam, void* pStack = 0,
208 bool semiUser = false, bool bDontPickCore = false, bool delayedStart = false,
209 const ThreadPlacement* placement = nullptr);
210
213 Thread(Process* pParent);
214
218 Thread(Process* pParent, SyscallState& state, bool delayedStart = false,
219 const ThreadPlacement* placement = nullptr);
220
221 void snapshotPlacement(ThreadPlacement& placement);
223 void snapshotPlacementLocked(ThreadPlacement& placement) const;
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;
236 }
237#if PEDIGREE_AFFINITY_TESTS
238 using AffinityCommitHook = void (*)(Thread*);
239 static void setAffinityCommitHookForTest(Thread* target, AffinityCommitHook hook);
240#endif
241
246 virtual ~Thread();
247
254 void shutdown();
255
260 void notifySubsystemExit();
261 /* Forces the thread to run on the bootstrap processor. */
262 void forceToStartupProcessor();
263
266 SchedulerState& state();
267
272 SchedulerState* pushState();
273
278 void popState(bool clean = true);
279
281 void abandonCurrentState(bool clean = false);
282
284 void abandonAllStates();
285
286 VirtualAddressSpace::Stack* getStateUserStack();
287
288 void setStateUserStack(VirtualAddressSpace::Stack* st);
289
295 void discardUserStackMetadataForExec();
296
298 void adoptInitialUserStackForExec(VirtualAddressSpace::Stack* stack);
299
301 size_t getStateLevel() const {
302 return __atomic_load_n(&m_nStateLevel, __ATOMIC_ACQUIRE);
303 }
304
305 void* getSyscallDispatchContext() const {
306 return m_SyscallDispatchContext;
307 }
308 void setSyscallDispatchContext(void* context) {
309 m_SyscallDispatchContext = context;
310 }
311
313 void allocateStackAtLevel(size_t stateLevel);
314
316 void setKernelStack();
317
322 void pokeState(size_t stateLevel, SchedulerState& state);
323
326 return m_pParent;
327 }
328
330 void setClearChildTid(uintptr_t address);
331
333 uintptr_t takeClearChildTid() {
334 return __atomic_exchange_n(&m_ClearChildTid, static_cast<uintptr_t>(0), __ATOMIC_ACQ_REL);
335 }
336
337 void setRobustList(uintptr_t address, size_t ownerId);
338
339 uintptr_t getRobustList() const {
340 return __atomic_load_n(&m_RobustList, __ATOMIC_ACQUIRE);
341 }
342
343 uintptr_t takeRobustList(size_t& ownerId);
344
346 void recordTime(CpuTimeMode mode);
347
349 void trackTime(CpuTimeMode mode);
350
352 void transitionTime(CpuTimeMode from, CpuTimeMode to, bool interruptsAlreadyDisabled = false);
353
358 ALWAYS_INLINE void transitionTimeAtInterruptReturn(CpuTimeMode from, CpuTimeMode to) {
359 if constexpr (PEDIGREE_TIME_ACCOUNTING && !PEDIGREE_SAMPLED_TIME_ACCOUNTING) {
361 // The architecture boundary owns the physical IRQ mask. Going
362 // through CpuTimeSample here could momentarily undo that mask on hosted,
363 // where the logical state intentionally describes the pending sigreturn.
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);
369 if (elapsed) {
370 publishTimeAccounting(from, elapsed);
371 }
372 } else {
373 (void)from;
374 __atomic_store_n(&m_CurrentTimeAccountingMode, static_cast<size_t>(to), __ATOMIC_RELEASE);
375 }
376 }
377
379 CpuTimeMode currentTimeAccountingMode() const;
380
382 void accountTimerTick(Time::Timestamp delta, bool kernelMode);
383
384#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
385 static constexpr size_t NoSyscallTimingSlot = ~static_cast<size_t>(0);
386
387 size_t installSyscallTimingSlot(size_t slot) {
388 return __atomic_exchange_n(&m_ActiveSyscallTimingSlot, slot, __ATOMIC_ACQ_REL);
389 }
390
391 void restoreSyscallTimingSlot(size_t slot) {
392 __atomic_store_n(&m_ActiveSyscallTimingSlot, slot, __ATOMIC_RELEASE);
393 }
394#endif
395
397 Time::Timestamp getUserTime() const {
398 return __atomic_load_n(&m_UserTime, __ATOMIC_ACQUIRE);
399 }
400 Time::Timestamp getKernelTime() const {
401 return __atomic_load_n(&m_KernelTime, __ATOMIC_ACQUIRE);
402 }
403
404#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
406 void publishTimeAccountingForHostedTest(Time::Timestamp user, Time::Timestamp system);
407#endif
408
409 void setParent(Process* p) {
410 m_pParent = p;
411 }
412
413 ExecutionPersonality& executionPersonality() {
414 return m_ExecutionPersonality;
415 }
416
419 return m_Status;
420 }
421
428 bool start();
429
436 bool startDetached();
437
440 return m_ExitCode;
441 }
442
444 void* getKernelStack();
445
447 void* getKernelStackBase(size_t* size) const;
448
450 size_t getId() {
451 return m_Id;
452 }
453
455 size_t getTaskId() const {
456 return __atomic_load_n(&m_TaskId, __ATOMIC_ACQUIRE);
457 }
458
460 size_t getErrno() {
461 return m_StateLevels[m_nStateLevel].m_Errno;
462 }
463
465 void setErrno(size_t err) {
466 m_StateLevels[m_nStateLevel].m_Errno = err;
467 }
468
469 enum InterruptionReason {
470 NotInterrupted,
471 InterruptedByTimeout,
472 InterruptedBySignal,
473 };
474
477 return getInterruptionReason() != NotInterrupted;
478 }
479
480 void clearInterruption() {
481 m_StateLevels[m_nStateLevel].m_InterruptionReason = NotInterrupted;
482 }
483
484 InterruptionReason getInterruptionReason() {
485 return m_StateLevels[m_nStateLevel].m_InterruptionReason;
486 }
487
488 void setInterruptionReason(InterruptionReason reason) {
489 m_StateLevels[m_nStateLevel].m_InterruptionReason = reason;
490 }
491
493 void markTimeoutInterruptedWait();
494
496 void markSignalInterruptedWait();
497
500 Continue = 0,
502 TerminateThread
503 };
504
519 return __atomic_load_n(&m_UnwindState, __ATOMIC_ACQUIRE);
520 }
522 void setUnwindState(UnwindType ut);
523
525 void deferProcessExit(int code);
526
528 void deferSignalExit(int signal);
529
531 int code;
533 };
534
536 DeferredProcessExit takeDeferredProcessExit();
537
542 bool deferSubsystemException(size_t type, uintptr_t faultAddress, uintptr_t errorCode);
543
544 bool hasDeferredSubsystemException() const {
545 return __atomic_load_n(&m_DeferredSubsystemExceptionState, __ATOMIC_ACQUIRE) != 0;
546 }
547
549 bool takeDeferredSubsystemException(size_t& type, uintptr_t& faultAddress, uintptr_t& errorCode);
550
553 return __atomic_load_n(&m_TerminationDeferralDepth, __ATOMIC_ACQUIRE) != 0;
554 }
555
557 DebugState getDebugState(uintptr_t& address) {
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) {
561 continue;
562 }
563
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;
568 return state;
569 }
570 }
571
572 address = 0;
573 return None;
574 }
576 void setDebugState(DebugState state, uintptr_t address) {
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);
581 }
582
584 WaitQueue* queue;
585 const void* channelOwner;
586 uintptr_t channelValue;
587 WaitQueue::WakeReason reason;
588 size_t stateLevel;
589 bool queued;
590 };
591
593 bool getWaitDebugInfo(WaitDebugInfo& info);
594
597 return m_Lock;
598 }
599
607 bool sendEvent(Event* pEvent);
608
610 void waitForEvent(WaitQueue::StackDiscardCleanup onStackDiscard = nullptr,
611 void* stackDiscardContext = nullptr);
612
617 bool waitForEventOrSignalInterruption(WaitQueue::StackDiscardCleanup onStackDiscard = nullptr,
618 void* stackDiscardContext = nullptr);
619
620#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
621 enum StateTransitionWindow {
622 StatePushBeforePublish,
623 StatePushAfterPublish,
624 StatePopAfterPublish,
625 };
626 enum ExternalLeaseReleasePhase {
627 ExternalLeaseFinalReleaseUnlocked,
628 ExternalLeaseBeforeWaiterWake,
629 };
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);
636
638 static void setStateTransitionHook(StateTransitionHook hook);
639
641 static void setJoinOperationHook(JoinOperationHook hook);
642
644 static void setExternalLeaseReleaseHookForHostedTest(Thread* target,
645 ExternalLeaseReleaseHook hook);
646
648 static void setSignalWaitPreEnrolmentHookForHostedTest(Thread* target,
649 SignalWaitPreEnrolmentHook hook);
650
652 bool isReapableForHostedTest();
653
655 bool wasStartPublishedForHostedTest();
656
658 bool waitUntilReapableForHostedTest();
659
664 bool runHostedPrequeuedEventRegression();
665
667 bool runHostedEventDeliveryLeaseRegression();
668
670 bool runHostedEventShutdownRegression();
671
673 bool runHostedStatePublicationRegression();
674
676 bool runHostedStateCleanupRegression();
677
679 bool runHostedExecStackOwnershipRegression();
680
682 void withDeferredScopeLockForTest(DeferredScopeLockHook hook);
683#endif
684
688 void inhibitEvent(size_t eventNumber, bool bInhibit);
689
691 uint64_t getSignalMask();
692
694 void setSignalMask(uint64_t mask);
695
697 uint64_t getSignalMaskForReturnFrame();
698
700 void commitSignalHandlerMask(uint64_t mask);
701
703 void restoreDeferredSignalMask(size_t stateLevel);
704
706 const SyscallState* getOriginalSyscallState() const {
707 return m_OriginalSyscallState;
708 }
709
710 void setOriginalSyscallState(const SyscallState* state) {
711 m_OriginalSyscallState = state;
712 if (state) {
713 __atomic_fetch_or(&m_UserReturnWorkPending, UserReturnOriginalSyscall, __ATOMIC_RELEASE);
714 } else {
715 __atomic_fetch_and(&m_UserReturnWorkPending, ~static_cast<size_t>(UserReturnOriginalSyscall),
716 __ATOMIC_RELEASE);
717 }
718 }
719
721 void setCurrentSignalDelivery(size_t signalNumber, size_t continuationEpoch);
722
724 bool getCurrentSignalDelivery(size_t& signalNumber, size_t& continuationEpoch);
725
727 void prepareSignalStateForExec();
728
730 bool hasTemporarySignalWaitInterruption();
731
733 bool hasActiveTemporarySignalMask();
734
736 bool retainTemporarySignalWaitInterruptionOrClear();
737
739 AlternateSignalStack() : base(0), size(0), enabled(false), inUse(false) {}
740
741 uintptr_t base;
742 size_t size;
743 bool enabled;
744 bool inUse;
745 };
746
747 AlternateSignalStack& getAlternateSignalStack() {
748 return m_AlternateSignalStack;
749 }
750
752 void cullEvent(Event* pEvent);
753
756 void cullEvent(size_t eventNumber);
757
759 void cullSignalEvent(size_t signalNumber);
760
765 bool transferProcessSignalsTo(Thread& target);
766
772 bool replaceSignalEvent(size_t signalNumber, Event* replacement, int processDirected = -1,
773 uint64_t rebindGeneration = 0);
774
776 bool hasSignalEvent(size_t signalNumber, int processDirected = -1);
777
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));
783 bool restorePendingSignal(Event::Delivery& delivery);
784 void cullSignalSource(const void* source);
785 void setSynchronousSignalMask(uint64_t mask);
786 uint64_t getSynchronousSignalMask();
787
788 bool hasEvents();
789
791 bool hasEvent(Event* pEvent);
792 bool hasEvent(size_t eventNumber);
793
794 void setPriority(size_t p) {
795 m_Priority = p;
796 }
797 size_t getPriority() {
798 return m_Priority;
799 }
800
802 void unexpectedExit();
803
805 uintptr_t getTlsBase();
806
812 void resetTlsBase();
813
814#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
815 enum TlsResetPhase {
816 TlsResetBeforeClear,
817 TlsResetCleared,
818 TlsResetRemapped,
819 };
820 using TlsResetHook = void (*)(Thread* thread, TlsResetPhase phase, uintptr_t base);
821
823 static void setTlsResetHookForHostedTest(Thread* target, TlsResetHook hook);
824#endif
825
831 void setTlsBase(uintptr_t base);
832
833#if X64 && !HOSTED
834 uintptr_t getUserGsBase() const {
835 return m_UserGsBase;
836 }
837 void setUserGsBase(uintptr_t base);
838 void saveUserGsBase();
839#endif
840
842 inline
843#if MULTIPROCESSOR
845#else
846 size_t
847#endif
849 return m_ProcId;
850 }
851
853 inline void setCpuId(
854#if MULTIPROCESSOR
856#else
857 size_t
858#endif
859 id) {
860 m_ProcId = id;
861 }
862
870 bool join();
871
878 bool joinForCompletion();
879
888 bool detach();
889
893 bool detached() const {
894 return m_bDetached;
895 }
896
903 static void threadExited() NORETURN;
904
906 bool eventsDeferred() const;
907
909 ExecutionContext executionContext() const;
910
912 class PerProcessorScheduler* getScheduler() const {
913 return __atomic_load_n(&m_pScheduler, __ATOMIC_ACQUIRE);
914 }
915
916 const String& getName() const {
917 return m_Name;
918 }
919
920 void setName(const String& name) {
921 m_Name = name;
922 }
923
924 template <size_t N>
925 void setName(const char (&name)[N]) {
926 m_Name.assign(name, N);
927 }
928
929#if HOSTED
931 size_t enterHostedSignalHandler();
932
934 void leaveHostedSignalHandler(size_t stateLevel);
935
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);
939 }
940#endif
941
942 protected:
944 void setScheduler(class PerProcessorScheduler* pScheduler);
945
946 void deferEvents();
947 void resumeEvents();
948 void deferTermination();
949 void resumeTermination();
950 void markUserReturnWorkFlag(UserReturnWorkFlag flag) {
951 __atomic_fetch_or(&m_UserReturnWorkPending, static_cast<size_t>(flag), __ATOMIC_RELEASE);
952 }
953 void clearUserReturnWorkFlag(UserReturnWorkFlag flag) {
954 __atomic_fetch_and(&m_UserReturnWorkPending, ~static_cast<size_t>(flag), __ATOMIC_RELEASE);
955 }
956 void markUserReturnWorkPending() {
957 markUserReturnWorkFlag(UserReturnExternalWork);
958 }
959 void registerDeferredScope(DeferredScopeRecord& record, bool termination, bool events);
960 void armStateCleanup(DeferredScopeRecord& record, DeferredScopeRecord::Cleanup cleanup,
961 void* context);
962 void unregisterDeferredScope(DeferredScopeRecord& record);
963 void disarmStateCleanup(DeferredScopeRecord& record);
964 void unregisterTerminationDeferral(DeferredScopeRecord& record);
965 void moveTerminationDeferral(DeferredScopeRecord& from, DeferredScopeRecord& to);
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);
971 void armAtomicStateCleanup(AtomicStateCleanupRecord& record,
972 AtomicStateCleanupRecord::Cleanup cleanup, void* context);
973 void disarmAtomicStateCleanup(AtomicStateCleanupRecord& record);
974
975 private:
976 void registerFreshTerminationDeferral(DeferredScopeRecord& record,
977 DeferredScopeRecord::Cleanup cleanup = nullptr,
978 void* context = nullptr);
979
981 Thread(const Thread&);
984
986 void publishTimeAccounting(CpuTimeMode mode, Time::Timestamp elapsed);
987
988 void initialisePlacement(const ThreadPlacement* placement);
989 void publishReadyNotification();
990
992 void cleanStateLevel(size_t level);
993
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);
999
1000 enum class EventSelection {
1001 AnyDeliverable,
1002 WithoutExactUserReturn,
1003 KernelDeliverable,
1004 StoppedProcessKernel,
1005 };
1006
1008 bool eventNeedsUserReturnFrameUnlocked(Event* event) const;
1009 bool eventIsDeliverableUnlocked(Event* event,
1010 EventSelection selection = EventSelection::AnyDeliverable);
1011
1013 bool hasEventsUnlocked(EventSelection selection = EventSelection::AnyDeliverable);
1014 bool hasDeliverableEventsUnlocked(EventSelection selection = EventSelection::AnyDeliverable);
1015
1017 void markDeferredUserReturnSignalInterruption();
1018
1020 void wakeForDeliverableEvents();
1021
1023 MUST_USE_RESULT Event::Delivery getNextEvent(
1024 EventSelection selection = EventSelection::AnyDeliverable);
1025
1027 void setStatus(Status s);
1028 void setStatusUnlocked(Status s);
1029
1034 bool markReapable();
1035
1037 bool joinInternal(bool completion);
1038
1040 Thread* target;
1041 Process* parent;
1042 bool claimed;
1043 };
1044
1046 static void discardJoin(void* context);
1047
1049 bool beginExternalLease();
1050
1052 void endExternalLease();
1053
1055 void closeExternalLeaseAdmission();
1056
1058 void closeExternalLeaseAdmissionAndDrain();
1059
1061 bool interruptWaitUnlocked(WaitQueue::WakeReason reason, PerProcessorScheduler*& readyScheduler);
1062 bool hasActiveWaitUnlocked() const;
1063 bool hasActiveWaitAtAnyLevel() const;
1064 bool activeWaitPendingUnlocked() const;
1065
1067 void unlinkWaitsForStackDiscard();
1068
1074 void markTerminalWaitCancelledBeforeBlockUnlocked(size_t level);
1075 bool consumeTerminalWaitCancelledBeforeBlockUnlocked();
1076 void clearTerminalWaitCancelledBeforeBlockUnlocked(size_t level);
1077
1079 struct StateLevel {
1080 StateLevel();
1081 ~StateLevel();
1082
1083 StateLevel(const StateLevel& s);
1084 StateLevel& operator=(const StateLevel& s);
1085
1087 SchedulerState* m_State;
1088 UserReturnFrame* m_UserReturnFrame = nullptr;
1089
1092
1093 VirtualAddressSpace::Stack* m_pUserStack;
1094
1100
1107
1110
1113 bool m_TemporarySignalMaskActive;
1114 bool m_TemporarySignalWaitInterrupted;
1115 bool m_DeferredSignalMaskRestore;
1116
1119 size_t m_DispatchedSignalContinuationEpoch;
1120
1123
1125 size_t m_Errno;
1126 InterruptionReason m_InterruptionReason;
1127
1130
1133
1136
1143
1144#if HOSTED
1146 size_t m_HostedSignalDepth;
1147#endif
1148
1151 };
1152
1155
1157 size_t m_nStateLevel = 0;
1158
1160 Process* m_pParent = nullptr;
1161 // VFS uses task-local filesystem IDs even when the POSIX identity is shared.
1162 uint32_t m_FilesystemUid = 0, m_FilesystemGid = 0;
1163 bool m_FilesystemIdsValid = false;
1164 const FilesystemCredentials* m_FilesystemOverride = nullptr;
1165
1168
1171
1173 Time::Timestamp m_UserTime = 0;
1174 Time::Timestamp m_KernelTime = 0;
1175
1177 size_t m_CurrentTimeAccountingMode = static_cast<size_t>(CpuTimeMode::Kernel);
1178
1179#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1180 size_t m_ActiveSyscallTimingSlot = NoSyscallTimingSlot;
1181#endif
1182
1186 void* m_pAllocatedStack = nullptr;
1187
1189 size_t m_Id = 0;
1190 size_t m_TaskId = 0;
1191
1193 uintptr_t m_DebugStateAddress = 0;
1194
1196 size_t m_DebugStateGeneration = 0;
1197
1198 class PerProcessorScheduler* m_pScheduler = nullptr;
1199
1200 ThreadPlacement m_Placement;
1201 CpuAffinityMask m_RequestedAffinity;
1202 WaitQueue m_AffinityWaiters;
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;
1215
1217 size_t m_Priority = DEFAULT_PRIORITY;
1218
1220 Thread* m_pReadyPrevious = nullptr;
1221 Thread* m_pReadyNext = nullptr;
1222 size_t m_ReadyQueuePriority = MAX_PRIORITIES;
1223 bool m_bReadyQueued = false;
1224
1226 void* m_pTlsBase = nullptr;
1227#if X64 && !HOSTED
1228 uintptr_t m_UserGsBase = 0;
1229#endif
1230
1231#if MULTIPROCESSOR
1233#else
1234 size_t
1235#endif
1236 m_ProcId = 0;
1237
1240
1243
1246
1249
1251 size_t m_nExternalLeases = 0;
1252
1254 bool m_bExternalLeaseAdmissionClosed = false;
1255
1262 bool m_bExternalLeaseReleaseInProgress = false;
1263
1266
1269
1272
1274 size_t m_EventSendersInFlight = 0;
1275
1276 StateLevel m_StateLevels[MAX_NESTED_EVENTS];
1277
1280
1281 const SyscallState* m_OriginalSyscallState = nullptr;
1282 void* m_SyscallDispatchContext = nullptr;
1284 size_t m_ActiveSyscalls[serviceEnd] = {};
1285
1287 volatile Status m_Status = Ready;
1288 ExecutionPersonality m_ExecutionPersonality;
1289
1291 bool m_ExitToIdle = false;
1292
1294 int m_ExitCode = 0;
1295
1298 DebugState m_DebugState = None;
1299
1300 UnwindType m_UnwindState = Continue;
1301
1303 uint64_t m_DeferredProcessExitRequest = 0;
1304 uint64_t m_SynchronousSignalMask = 0;
1305
1307 size_t m_DeferredSubsystemExceptionState = 0;
1308 size_t m_DeferredSubsystemExceptionType = 0;
1309 uintptr_t m_DeferredSubsystemExceptionFaultAddress = 0;
1310 uintptr_t m_DeferredSubsystemExceptionErrorCode = 0;
1311
1313 bool m_bTlsBaseOverride = false;
1314
1316 bool m_bShutdown = false;
1317
1319 bool m_bSubsystemExitNotified = false;
1320
1322 uintptr_t m_ClearChildTid = 0;
1323
1325 uintptr_t m_RobustList = 0;
1326 size_t m_RobustListOwnerId = 0;
1327
1329 bool m_bStartRequested = false;
1330
1332 bool m_bDetached = false;
1333
1335 bool m_bJoinClaimed = false;
1336
1338 bool m_bDetachedRetirementClaimed = false;
1339
1341 bool m_bThreadExitRequested = false;
1342
1344 bool m_bExitStarted = false;
1345
1347 bool m_bReapable = false;
1348
1350 bool m_bProcessExitOwned = false;
1351
1353 bool m_bProcessExitParticipant = false;
1354
1356 size_t m_EventDeferralDepth = 0;
1357
1358#if PEDIGREE_LATENCY_ACCOUNTING
1360 Time::Timestamp m_EventDeferralStarted = 0;
1361#endif
1362
1364 size_t m_TerminationDeferralDepth = 0;
1365
1367 DeferredScopeRecord* m_pDeferredScopes[MAX_NESTED_EVENTS] = {};
1368 size_t m_NextStateCleanupSequence = 0;
1369
1370#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1371 Spinlock m_DeferredScopeRegressionLock;
1372#endif
1373};
1374
1375#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:1170
void setErrno(size_t err)
Definition Thread.h:465
WaitQueue m_JoinWaiters
Definition Thread.h:1242
WaitQueue m_EventWaiters
Definition Thread.h:1265
Thread(const Thread &)
AlternateSignalStack m_AlternateSignalStack
Definition Thread.h:1279
UnwindType
Definition Thread.h:499
@ Exit
Exit the owning process at the next safe boundary.
Definition Thread.h:501
void setDebugState(DebugState state, uintptr_t address)
Definition Thread.h:576
DebugState
Definition Thread.h:175
size_t getErrno()
Definition Thread.h:460
Time::Timestamp getUserTime() const
Definition Thread.h:397
WaitQueue m_ExternalLeaseWaiters
Definition Thread.h:1248
const SyscallState * getOriginalSyscallState() const
Definition Thread.h:706
Status getStatus() const
Definition Thread.h:418
UnwindType getUnwindState()
Definition Thread.h:518
DeferredThreadReapNode m_DeferredReapNode
Definition Thread.h:1167
uintptr_t takeClearChildTid()
Definition Thread.h:333
bool detached() const
Definition Thread.h:893
Spinlock m_Lock
Definition Thread.h:1239
ALWAYS_INLINE void transitionTimeAtInterruptReturn(CpuTimeMode from, CpuTimeMode to)
Definition Thread.h:358
DebugState getDebugState(uintptr_t &address)
Definition Thread.h:557
Process * getParent() const
Definition Thread.h:325
size_t getId()
Definition Thread.h:450
void setCpuId(size_t id)
Definition Thread.h:853
Spinlock m_ExternalLeaseLock
Definition Thread.h:1245
size_t getCpuId()
Definition Thread.h:848
int getExitCode()
Definition Thread.h:439
Spinlock & getLock()
Definition Thread.h:596
bool isTerminationDeferred() const
Definition Thread.h:552
Thread & operator=(const Thread &)
size_t getStateLevel() const
Definition Thread.h:301
size_t getTaskId() const
Definition Thread.h:455
WaitQueue m_EventSenderDrainWaiters
Definition Thread.h:1268
List< Event * > m_EventQueue
Definition Thread.h:1271
bool wasInterrupted()
Definition Thread.h:476
String m_Name
Definition Thread.h:1154
size_t ProcessorId
size_t m_DispatchedSignalNumber
Definition Thread.h:1118
VirtualAddressSpace::Stack * m_pKernelStack
Definition Thread.h:1091
WaitQueue::Waiter m_Waiter
Definition Thread.h:1150
uint64_t m_SignalMask
Definition Thread.h:1109
SharedPointer< ExtensibleBitmap > m_InhibitMask
Definition Thread.h:1106
uint64_t m_SavedSignalMask
Definition Thread.h:1112
RequestQueueCallbackScope * m_pRequestQueueCallback
Definition Thread.h:1135
bool m_bOwnsAlternateSignalStack
Definition Thread.h:1122
ExecutionContextState m_ExecutionContext
Definition Thread.h:1132
bool m_bDispatchingWaitEvent
Definition Thread.h:1129
SchedulerState * m_State
Definition Thread.h:1087
VirtualAddressSpace::Stack * m_pAuxillaryStack
Definition Thread.h:1099
bool m_bTerminalWaitCancelledBeforeBlock
Definition Thread.h:1142