86 explicit operator bool()
const {
90 void adoptLeaderIdentity();
105 explicit operator bool()
const {
106 return m_pProcess !=
nullptr;
128 explicit operator bool()
const {
129 return m_pProcess !=
nullptr;
165 Thread* operator->()
const {
169 explicit operator bool()
const {
170 return m_pThread !=
nullptr;
201 File* operator->()
const {
205 explicit operator bool()
const {
206 return m_pFile !=
nullptr;
219 void adopt(
File* file,
bool vfsReference);
223 bool m_bVfsReference;
239 explicit operator bool()
const {
240 return m_pProcess !=
nullptr;
244 void install(
Thread* owner);
277#if PEDIGREE_BENCHMARK_SYSCALL_TRACE
278 void setBenchmarkSyscallTrace(
bool enabled) {
279 __atomic_store_n(&m_BenchmarkSyscallTrace, enabled, __ATOMIC_RELEASE);
282 bool benchmarkSyscallTraceEnabled()
const {
283 return __atomic_load_n(&m_BenchmarkSyscallTrace, __ATOMIC_ACQUIRE);
287#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
288 static constexpr size_t SyscallTimingRawSlotCount = 512;
289 static constexpr size_t SyscallTimingOverflowSlot = SyscallTimingRawSlotCount;
290 static constexpr size_t SyscallTimingSlotCount = SyscallTimingRawSlotCount + 1;
292 struct SyscallTimingEntry {
294 uint64_t kernelNanoseconds;
297 static size_t syscallTimingSlot(
size_t rawNumber) {
298 return rawNumber < SyscallTimingRawSlotCount ? rawNumber : SyscallTimingOverflowSlot;
301 void setBenchmarkSyscallTiming(
bool enabled) {
302 __atomic_store_n(&m_BenchmarkSyscallTiming, enabled, __ATOMIC_RELEASE);
305 bool benchmarkSyscallTimingEnabled()
const {
306 return __atomic_load_n(&m_BenchmarkSyscallTiming, __ATOMIC_ACQUIRE);
309 void recordSyscallTimingCall(
size_t slot) {
310 __atomic_fetch_add(&m_SyscallTimingCalls[slot],
static_cast<uint64_t
>(1), __ATOMIC_RELAXED);
313 void recordSyscallTimingKernel(
size_t slot, Time::Timestamp elapsed) {
314 __atomic_fetch_add(&m_SyscallTimingKernelNanoseconds[slot], elapsed, __ATOMIC_RELAXED);
317 void getSyscallTimingEntry(
size_t slot, SyscallTimingEntry& result)
const {
318 result.calls = __atomic_load_n(&m_SyscallTimingCalls[slot], __ATOMIC_ACQUIRE);
319 result.kernelNanoseconds =
320 __atomic_load_n(&m_SyscallTimingKernelNanoseconds[slot], __ATOMIC_ACQUIRE);
324#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
325 enum BenchmarkVmCounter :
size_t {
327 VmMmapAnonymousCalls,
337 VmPublishObjectCount,
338 VmPublishOverlapProbeVisits,
339 VmPublishOverlapHits,
340 VmPublishCommitRetries,
341 VmReservationSnapshots,
342 VmReservationExtents,
343 VmReservationScratchAllocations,
349 VmMunmapLength16To63,
350 VmMunmapLength64To255,
351 VmMunmapLength256Plus,
354 VmRemoveObjectVisits,
356 VmRemoveAffectedObjects,
359 VmAllowsObjectVisits,
362 VmFaultInObjectVisits,
364 VmFaultInCopyOnWrite,
373 VmGuardRecursiveEntries,
374 VmDiscardTrackedPages,
375 VmDiscardMappedPages,
376 VmTableRetirementScans,
381 VmInvalidationActive,
382 VmInvalidationInactive,
383 BenchmarkVmCounterCount,
386 void setBenchmarkVmDiagnostics(
bool enabled) {
387 __atomic_store_n(&m_BenchmarkVmDiagnostics, enabled, __ATOMIC_RELEASE);
390 bool benchmarkVmDiagnosticsEnabled()
const {
391 return __atomic_load_n(&m_BenchmarkVmDiagnostics, __ATOMIC_ACQUIRE);
394 void recordBenchmarkVmCounter(BenchmarkVmCounter counter, uint64_t amount = 1) {
395 if (benchmarkVmDiagnosticsEnabled() && amount) {
396 __atomic_fetch_add(&m_BenchmarkVmCounters[counter], amount, __ATOMIC_RELAXED);
400 uint64_t getBenchmarkVmCounter(
size_t counter)
const {
401 return __atomic_load_n(&m_BenchmarkVmCounters[counter], __ATOMIC_ACQUIRE);
422 size_t addThread(
Thread* pThread);
424 void threadExiting(
Thread* pThread);
426 void transferExecProcessSignals(
Thread* pThread);
428 void removeThread(
Thread* pThread);
431 size_t getNumThreads();
447 MUST_USE_RESULT bool acquireThreadByTaskId(ThreadLease& lease,
size_t id);
460 TerminalOwnerReservation reserveTerminalOwner();
469 return m_UserspaceId;
479 return m_pAddressSpace;
489 bool m_Complete =
false;
494 return m_pVforkOwner ? m_pVforkOwner :
this;
496 bool isVforkChild()
const {
497 return m_pVforkOwner !=
nullptr;
501 void releaseVforkAddressSpace();
512 enum class ChildTransitionKind {
521 ChildTransitionKind kind;
534 bool prepareThreadExit();
547 bool quiesceTermination();
550 void finishTermination(
bool notifyParent =
false)
NORETURN;
558 void suspend(
int stopSignal = 0);
560 void suspendIfContinuationEpoch(
int stopSignal,
size_t continuationEpoch);
565 size_t getContinuationEpoch();
569 return __atomic_load_n(&m_pParent, __ATOMIC_ACQUIRE);
572 enum class FilesystemContextMode { Inherit, Deferred };
577 bool filesystemContextReady()
const;
578 void releaseFilesystemContext();
583 virtual File* file()
const = 0;
604 bool allocateUserRange(
UserRegion region,
size_t length, uintptr_t& address);
605 bool allocateSpecificUserRange(
UserRegion region, uintptr_t address,
size_t length);
606 void freeUserRange(
UserRegion region, uintptr_t address,
size_t length);
607 void resetUserReservations();
612 virtual bool installUserIdentity(
User*,
Group*,
const uint32_t* groups,
size_t count);
630 User* getUser()
const;
632 void setUser(
User* pUser);
635 User* getEffectiveUser()
const;
637 void setEffectiveUser(
User* pUser);
640 Group* getGroup()
const;
642 void setGroup(
Group* pGroup);
645 Group* getEffectiveGroup()
const;
646 void setEffectiveGroup(
Group* pGroup);
650 virtual int64_t getUserId()
const;
651 virtual int64_t getGroupId()
const;
652 virtual int64_t getEffectiveUserId()
const;
653 virtual int64_t getEffectiveGroupId()
const;
655 virtual void setUserId(int64_t
id);
656 virtual void setGroupId(int64_t
id);
657 virtual void setEffectiveUserId(int64_t
id);
658 virtual void setEffectiveGroupId(int64_t
id);
661 m_pDynamicLinker = pDl;
664 return m_pDynamicLinker;
667 void setSubsystem(
Subsystem* pSubsystem) {
668 m_pSubsystem = pSubsystem;
675 ProcessType getType()
const {
683 return m_ChildStateWaiters.acquire();
690 bool waitUntilTerminationReapable();
696 bool waitUntilTerminationReapableForTerminalCoordinator();
703 bool selectPendingChildTransition(
bool includeStopped,
bool includeContinued,
bool consume,
704 ChildTransition& transition);
707 bool takePendingChildTransition(
bool includeStopped,
bool includeContinued,
708 ChildTransition& transition);
710 ProcessState getState()
const {
711 return __atomic_load_n(&m_State, __ATOMIC_ACQUIRE);
715 return getState() == Suspended;
718 void markTerminating();
720#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
722 static void setTerminationElectionHook(TerminationElectionHook hook);
724 enum ExternalLeaseReleasePhase {
725 ExternalLeaseFinalReleaseUnlocked,
726 ExternalLeaseBeforeWaiterWake,
728 using ExternalLeaseReleaseHook = void (*)(
Process*, ExternalLeaseReleasePhase);
729 static void setExternalLeaseReleaseHookForHostedTest(
Process* target,
730 ExternalLeaseReleaseHook hook);
733 bool isTerminationReapableForHostedTest();
735 enum class OrphanPublicationPhase {
739 using OrphanPublicationHook = void (*)(
Process*, OrphanPublicationPhase,
bool interruptsEnabled,
740 bool processLockHeld);
741 static void setOrphanPublicationHook(OrphanPublicationHook hook);
744 void publishTimeAccountingForHostedTest(Time::Timestamp user, Time::Timestamp system);
747 void closeTimeAccountingForHostedTest();
749 bool timeAccountingPendingForHostedTest()
const {
750 return m_DeferredTimeAccounting.pending();
752 size_t timeAccountingInterestForHostedTest()
const {
753 return __atomic_load_n(&m_TimeAccountingReportInterest, __ATOMIC_ACQUIRE);
757 void trackHeap(ssize_t nBytes) {
758 __atomic_fetch_add(&m_Metadata.heapUsage, nBytes, __ATOMIC_RELAXED);
761 void trackPages(ssize_t nVirtual, ssize_t nPhysical, ssize_t nShared) {
762 __atomic_fetch_add(&m_Metadata.virtualPages, nVirtual, __ATOMIC_RELAXED);
763 __atomic_fetch_add(&m_Metadata.physicalPages, nPhysical, __ATOMIC_RELAXED);
764 __atomic_fetch_add(&m_Metadata.sharedPages, nShared, __ATOMIC_RELAXED);
768 __atomic_store_n(&m_Metadata.virtualPages,
static_cast<ssize_t
>(0), __ATOMIC_RELEASE);
769 __atomic_store_n(&m_Metadata.physicalPages,
static_cast<ssize_t
>(0), __ATOMIC_RELEASE);
770 __atomic_store_n(&m_Metadata.sharedPages,
static_cast<ssize_t
>(0), __ATOMIC_RELEASE);
771 __atomic_store_n(&m_Metadata.startTime, Time::getTimeNanoseconds(), __ATOMIC_RELEASE);
776 return m_PerCpuTimeAccounting.total(CpuTimeMode::User) +
777 __atomic_load_n(&m_Metadata.userTime, __ATOMIC_ACQUIRE);
779 Time::Timestamp getKernelTime()
const {
780 return m_PerCpuTimeAccounting.total(CpuTimeMode::Kernel) +
781 __atomic_load_n(&m_Metadata.kernelTime, __ATOMIC_ACQUIRE);
783 Time::Timestamp getReapedChildrenUserTime()
const {
784 return __atomic_load_n(&m_Metadata.reapedChildrenUserTime, __ATOMIC_ACQUIRE);
786 Time::Timestamp getReapedChildrenKernelTime()
const {
787 return __atomic_load_n(&m_Metadata.reapedChildrenKernelTime, __ATOMIC_ACQUIRE);
790#if PEDIGREE_SYSCALL_COUNTER
791 static constexpr size_t SyscallLatencyBucketCount = 16;
793 struct SyscallLatencySnapshot {
794 uint64_t buckets[SyscallLatencyBucketCount];
798 void recordSyscall() {
799 __atomic_fetch_add(&m_Metadata.syscallCount,
static_cast<uint64_t
>(1), __ATOMIC_RELAXED);
803 void recordSyscallDuration(Time::Timestamp duration) {
805 Time::Timestamp limit = Time::Multiplier::Microsecond;
806 while (bucket + 1 < SyscallLatencyBucketCount && duration >= limit) {
810 __atomic_fetch_add(&m_Metadata.syscallLatencyBuckets[bucket],
static_cast<uint64_t
>(1),
814 uint64_t getSyscallCount()
const {
815 return __atomic_load_n(&m_Metadata.syscallCount, __ATOMIC_ACQUIRE);
818 uint64_t getReapedChildrenSyscallCount()
const {
819 return __atomic_load_n(&m_Metadata.reapedChildrenSyscallCount, __ATOMIC_ACQUIRE);
822 void getSyscallLatencySnapshot(SyscallLatencySnapshot& snapshot)
const {
823 for (
size_t i = 0; i < SyscallLatencyBucketCount; ++i) {
824 snapshot.buckets[i] =
825 __atomic_load_n(&m_Metadata.syscallLatencyBuckets[i], __ATOMIC_ACQUIRE) +
826 __atomic_load_n(&m_Metadata.reapedChildrenSyscallLatencyBuckets[i], __ATOMIC_ACQUIRE);
830 void getReapedChildrenSyscallLatencySnapshot(SyscallLatencySnapshot& snapshot)
const {
831 for (
size_t i = 0; i < SyscallLatencyBucketCount; ++i) {
832 snapshot.buckets[i] =
833 __atomic_load_n(&m_Metadata.reapedChildrenSyscallLatencyBuckets[i], __ATOMIC_ACQUIRE);
843 void accountReapedChild(
const Process* child, Time::Timestamp& user, Time::Timestamp& kernel);
845 Time::Timestamp getStartTime()
const {
846 return __atomic_load_n(&m_Metadata.startTime, __ATOMIC_ACQUIRE);
851 return __atomic_load_n(&m_Metadata.heapUsage, __ATOMIC_ACQUIRE);
853 ssize_t getVirtualPageCount()
const {
854 return __atomic_load_n(&m_Metadata.virtualPages, __ATOMIC_ACQUIRE);
856 ssize_t getPhysicalPageCount()
const {
857 return __atomic_load_n(&m_Metadata.physicalPages, __ATOMIC_ACQUIRE);
859 ssize_t getSharedPageCount()
const {
860 return __atomic_load_n(&m_Metadata.sharedPages, __ATOMIC_ACQUIRE);
868 return m_bSharedAddressSpace;
878 static void setInit(
Process* pProcess);
882 static bool loadFilesystemIds(
const Thread&, uint32_t& uid, uint32_t& gid);
883 static void publishFilesystemIds(
Thread&, uint32_t uid, uint32_t gid);
884 void publishAccountIdentity(
User*,
Group*);
894 FilesystemContextMode filesystemContext = FilesystemContextMode::Inherit,
895 bool emptyAddressSpace =
false,
ProcessType type = Stock);
900#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
905 void makeOrphanBeforePublicationForHostedTest();
914 void prepareForDestruction();
917 void enableTimeAccountingReports(
size_t initialInterest = ~
size_t(0));
920 void setTimeAccountingReportInterest(
size_t interest,
bool enabled);
923 void finishTermination(
bool abandonStack,
bool notifyParent)
NORETURN;
935 void drainDeferredTimeAccounting();
938 void closeDeferredTimeAccounting();
943 if (!m_PerCpuTimeAccounting.add(mode, elapsed, processor)) {
944 Time::Timestamp* total =
945 mode == CpuTimeMode::User ? &m_Metadata.userTime : &m_Metadata.kernelTime;
946 __atomic_fetch_add(total, elapsed, __ATOMIC_RELAXED);
948 reportTimeAccounting(elapsed);
951 ALWAYS_INLINE void reportTimeAccounting(Time::Timestamp elapsed) {
954 if (__atomic_load_n(&m_TimeAccountingReportInterest, __ATOMIC_ACQUIRE) &&
955 __atomic_load_n(&m_bTimeAccountingReportsEnabled, __ATOMIC_ACQUIRE)) {
956 queueTimeAccountingReport(elapsed);
960 void queueTimeAccountingReport(Time::Timestamp elapsed);
994 Process* m_pVforkOwner =
nullptr;
1001 bool m_bFilesystemContextReady;
1015 uint64_t m_UserReservationGeneration;
1017#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1018 bool m_BenchmarkSyscallTiming =
false;
1019 uint64_t m_SyscallTimingCalls[SyscallTimingSlotCount] = {};
1020 uint64_t m_SyscallTimingKernelNanoseconds[SyscallTimingSlotCount] = {};
1023#if PEDIGREE_BENCHMARK_SYSCALL_TRACE
1024 bool m_BenchmarkSyscallTrace =
false;
1027#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
1028 bool m_BenchmarkVmDiagnostics =
false;
1029 uint64_t m_BenchmarkVmCounters[BenchmarkVmCounterCount] = {};
1104 void suspendInternal(
int stopSignal,
bool checkContinuationEpoch,
size_t continuationEpoch);
1107 void transitionToTerminating();
1123 bool m_bExecCommitted =
false;
1124 bool m_bExecExitForwarded =
false;
1125 size_t m_nThreadCreations = 0;
1166 bool terminatingThreadReapable(
Thread* pThread,
bool& wakeOwner);
1169 void publishTerminationStatus(
bool notifyParent);
1172 void publishTerminationReapable();
1175 void publishReaperClaim();
1178 bool beginThreadJoin();
1181 void endThreadJoin();
1184 bool beginExternalLease();
1187 void endExternalLease();
1190 void closeExternalLeaseAdmission();
1193 void drainExternalLeases();
1196 void releaseThreadLease(
Thread* thread);
1199 void installTerminalOwner(
Thread* owner);
1203#if PEDIGREE_SYSCALL_COUNTER
1211 reapedChildrenUserTime(0),
1212 reapedChildrenKernelTime(0),
1214 reapedChildrenSyscallCount(0),
1215 syscallLatencyBuckets{},
1216 reapedChildrenSyscallLatencyBuckets{},
1226 reapedChildrenUserTime(0),
1227 reapedChildrenKernelTime(0),
1243 Time::Timestamp kernelTime;
1249#if PEDIGREE_SYSCALL_COUNTER
1251 uint64_t syscallCount;
1253 uint64_t reapedChildrenSyscallCount;
1255 uint64_t syscallLatencyBuckets[SyscallLatencyBucketCount];
1257 uint64_t reapedChildrenSyscallLatencyBuckets[SyscallLatencyBucketCount];
1283 size_t m_TimeAccountingReportInterest;
1291#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1292 static TerminationElectionHook m_TerminationElectionHook;
1293 static ExternalLeaseReleaseHook m_ExternalLeaseReleaseHook;
1294 static Process* m_ExternalLeaseReleaseTarget;
1295 static OrphanPublicationHook m_OrphanPublicationHook;