122 explicit operator bool()
const {
126 void adoptLeaderIdentity();
141 explicit operator bool()
const {
142 return m_pProcess !=
nullptr;
164 explicit operator bool()
const {
165 return m_pProcess !=
nullptr;
201 Thread* operator->()
const {
205 explicit operator bool()
const {
206 return m_pThread !=
nullptr;
238 File* operator->()
const {
242 explicit operator bool()
const {
243 return m_pFile !=
nullptr;
273 explicit operator bool()
const {
274 return m_pProcess !=
nullptr;
278 void install(
Thread* owner);
311#if PEDIGREE_BENCHMARK_SYSCALL_TRACE
312 void setBenchmarkSyscallTrace(
bool enabled) {
313 __atomic_store_n(&m_BenchmarkSyscallTrace, enabled, __ATOMIC_RELEASE);
316 bool benchmarkSyscallTraceEnabled()
const {
317 return __atomic_load_n(&m_BenchmarkSyscallTrace, __ATOMIC_ACQUIRE);
321#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
322 static constexpr size_t SyscallTimingRawSlotCount = 512;
323 static constexpr size_t SyscallTimingOverflowSlot = SyscallTimingRawSlotCount;
324 static constexpr size_t SyscallTimingSlotCount = SyscallTimingRawSlotCount + 1;
326 struct SyscallTimingEntry {
328 uint64_t kernelNanoseconds;
331 static size_t syscallTimingSlot(
size_t rawNumber) {
332 return rawNumber < SyscallTimingRawSlotCount ? rawNumber : SyscallTimingOverflowSlot;
335 void setBenchmarkSyscallTiming(
bool enabled) {
336 __atomic_store_n(&m_BenchmarkSyscallTiming, enabled, __ATOMIC_RELEASE);
339 bool benchmarkSyscallTimingEnabled()
const {
340 return __atomic_load_n(&m_BenchmarkSyscallTiming, __ATOMIC_ACQUIRE);
343 void recordSyscallTimingCall(
size_t slot) {
344 __atomic_fetch_add(&m_SyscallTimingCalls[slot],
static_cast<uint64_t
>(1), __ATOMIC_RELAXED);
347 void recordSyscallTimingKernel(
size_t slot, Time::Timestamp elapsed) {
348 __atomic_fetch_add(&m_SyscallTimingKernelNanoseconds[slot], elapsed, __ATOMIC_RELAXED);
351 void getSyscallTimingEntry(
size_t slot, SyscallTimingEntry& result)
const {
352 result.calls = __atomic_load_n(&m_SyscallTimingCalls[slot], __ATOMIC_ACQUIRE);
353 result.kernelNanoseconds =
354 __atomic_load_n(&m_SyscallTimingKernelNanoseconds[slot], __ATOMIC_ACQUIRE);
358#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
359 enum BenchmarkVmCounter :
size_t {
361 VmMmapAnonymousCalls,
371 VmPublishObjectCount,
372 VmPublishOverlapProbeVisits,
373 VmPublishOverlapHits,
374 VmPublishCommitRetries,
375 VmReservationSnapshots,
376 VmReservationExtents,
377 VmReservationScratchAllocations,
383 VmMunmapLength16To63,
384 VmMunmapLength64To255,
385 VmMunmapLength256Plus,
388 VmRemoveObjectVisits,
390 VmRemoveAffectedObjects,
393 VmAllowsObjectVisits,
396 VmFaultInObjectVisits,
398 VmFaultInCopyOnWrite,
407 VmGuardRecursiveEntries,
408 VmDiscardTrackedPages,
409 VmDiscardMappedPages,
410 VmTableRetirementScans,
415 VmInvalidationActive,
416 VmInvalidationInactive,
417 BenchmarkVmCounterCount,
420 void setBenchmarkVmDiagnostics(
bool enabled) {
421 __atomic_store_n(&m_BenchmarkVmDiagnostics, enabled, __ATOMIC_RELEASE);
424 bool benchmarkVmDiagnosticsEnabled()
const {
425 return __atomic_load_n(&m_BenchmarkVmDiagnostics, __ATOMIC_ACQUIRE);
428 void recordBenchmarkVmCounter(BenchmarkVmCounter counter, uint64_t amount = 1) {
429 if (benchmarkVmDiagnosticsEnabled() && amount) {
430 __atomic_fetch_add(&m_BenchmarkVmCounters[counter], amount, __ATOMIC_RELAXED);
434 uint64_t getBenchmarkVmCounter(
size_t counter)
const {
435 return __atomic_load_n(&m_BenchmarkVmCounters[counter], __ATOMIC_ACQUIRE);
456 size_t addThread(
Thread* pThread);
458 void threadExiting(
Thread* pThread);
460 void transferExecProcessSignals(
Thread* pThread);
462 void removeThread(
Thread* pThread);
465 size_t getNumThreads();
481 MUST_USE_RESULT bool acquireThreadByTaskId(ThreadLease& lease,
size_t id);
482 MUST_USE_RESULT bool acquireThreadByUserspaceId(ThreadLease& lease,
size_t id,
496 TerminalOwnerReservation reserveTerminalOwner();
505 return m_UserspacePid ? m_UserspacePid->id() : 0;
509 return m_UserspacePid ? m_UserspacePid->id(space) : 0;
512 return m_UserspaceNamespace;
515 return m_UserspacePid;
519 bool createPidNamespace();
520 bool unsharePidNamespace();
522 bool pidNamespaceReady()
const;
531 return m_pAddressSpace;
541 bool m_Complete =
false;
546 return m_pVforkOwner ? m_pVforkOwner :
this;
548 bool isVforkChild()
const {
549 return m_pVforkOwner !=
nullptr;
553 void releaseVforkAddressSpace();
564 enum class ChildTransitionKind {
573 ChildTransitionKind kind;
586 bool prepareThreadExit();
599 bool quiesceTermination();
602 void finishTermination(
bool notifyParent =
false)
NORETURN;
610 void suspend(
int stopSignal = 0);
612 void suspendIfContinuationEpoch(
int stopSignal,
size_t continuationEpoch);
617 size_t getContinuationEpoch();
621 return __atomic_load_n(&m_pParent, __ATOMIC_ACQUIRE);
624 enum class FilesystemContextMode { Inherit, Deferred };
631 bool filesystemContextReady()
const;
632 void releaseFilesystemContext();
637 virtual File* file()
const = 0;
658 bool allocateUserRange(
UserRegion region,
size_t length, uintptr_t& address);
659 bool allocateSpecificUserRange(
UserRegion region, uintptr_t address,
size_t length);
660 void freeUserRange(
UserRegion region, uintptr_t address,
size_t length);
661 void resetUserReservations();
666 virtual bool installUserIdentity(
User*,
Group*,
const uint32_t* groups,
size_t count);
684 User* getUser()
const;
686 void setUser(
User* pUser);
689 User* getEffectiveUser()
const;
691 void setEffectiveUser(
User* pUser);
694 Group* getGroup()
const;
696 void setGroup(
Group* pGroup);
699 Group* getEffectiveGroup()
const;
700 void setEffectiveGroup(
Group* pGroup);
704 virtual int64_t getUserId()
const;
705 virtual int64_t getGroupId()
const;
706 virtual int64_t getEffectiveUserId()
const;
707 virtual int64_t getEffectiveGroupId()
const;
709 virtual void setUserId(int64_t
id);
710 virtual void setGroupId(int64_t
id);
711 virtual void setEffectiveUserId(int64_t
id);
712 virtual void setEffectiveGroupId(int64_t
id);
715 m_pDynamicLinker = pDl;
718 return m_pDynamicLinker;
721 void setSubsystem(
Subsystem* pSubsystem) {
722 m_pSubsystem = pSubsystem;
729 ProcessType getType()
const {
737 return m_ChildStateWaiters.acquire();
744 bool waitUntilTerminationReapable();
750 bool waitUntilTerminationReapableForTerminalCoordinator();
757 bool selectPendingChildTransition(
bool includeStopped,
bool includeContinued,
bool consume,
758 ChildTransition& transition);
761 bool takePendingChildTransition(
bool includeStopped,
bool includeContinued,
762 ChildTransition& transition);
764 ProcessState getState()
const {
765 return __atomic_load_n(&m_State, __ATOMIC_ACQUIRE);
769 return getState() == Suspended;
772 void markTerminating();
774#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
776 static void setTerminationElectionHook(TerminationElectionHook hook);
778 enum ExternalLeaseReleasePhase {
779 ExternalLeaseFinalReleaseUnlocked,
780 ExternalLeaseBeforeWaiterWake,
782 using ExternalLeaseReleaseHook = void (*)(
Process*, ExternalLeaseReleasePhase);
783 static void setExternalLeaseReleaseHookForHostedTest(
Process* target,
784 ExternalLeaseReleaseHook hook);
787 bool isTerminationReapableForHostedTest();
789 enum class OrphanPublicationPhase {
793 using OrphanPublicationHook = void (*)(
Process*, OrphanPublicationPhase,
bool interruptsEnabled,
794 bool processLockHeld);
795 static void setOrphanPublicationHook(OrphanPublicationHook hook);
798 void publishTimeAccountingForHostedTest(Time::Timestamp user, Time::Timestamp system);
801 void closeTimeAccountingForHostedTest();
803 bool timeAccountingPendingForHostedTest()
const {
804 return m_DeferredTimeAccounting.pending();
806 size_t timeAccountingInterestForHostedTest()
const {
807 return __atomic_load_n(&m_TimeAccountingReportInterest, __ATOMIC_ACQUIRE);
811 void trackHeap(ssize_t nBytes) {
812 __atomic_fetch_add(&m_Metadata.heapUsage, nBytes, __ATOMIC_RELAXED);
815 void trackPages(ssize_t nVirtual, ssize_t nPhysical, ssize_t nShared) {
816 __atomic_fetch_add(&m_Metadata.virtualPages, nVirtual, __ATOMIC_RELAXED);
817 __atomic_fetch_add(&m_Metadata.physicalPages, nPhysical, __ATOMIC_RELAXED);
818 __atomic_fetch_add(&m_Metadata.sharedPages, nShared, __ATOMIC_RELAXED);
822 __atomic_store_n(&m_Metadata.virtualPages,
static_cast<ssize_t
>(0), __ATOMIC_RELEASE);
823 __atomic_store_n(&m_Metadata.physicalPages,
static_cast<ssize_t
>(0), __ATOMIC_RELEASE);
824 __atomic_store_n(&m_Metadata.sharedPages,
static_cast<ssize_t
>(0), __ATOMIC_RELEASE);
825 __atomic_store_n(&m_Metadata.startTime, Time::getTimeNanoseconds(), __ATOMIC_RELEASE);
830 return totalTime(CpuTimeMode::User);
832 Time::Timestamp getKernelTime()
const {
833 return totalTime(CpuTimeMode::Kernel);
835 Time::Timestamp getReapedChildrenUserTime()
const {
836 return __atomic_load_n(&m_Metadata.reapedChildrenUserTime, __ATOMIC_ACQUIRE);
838 Time::Timestamp getReapedChildrenKernelTime()
const {
839 return __atomic_load_n(&m_Metadata.reapedChildrenKernelTime, __ATOMIC_ACQUIRE);
842#if PEDIGREE_SYSCALL_COUNTER
843 static constexpr size_t SyscallLatencyBucketCount = 16;
845 struct SyscallLatencySnapshot {
846 uint64_t buckets[SyscallLatencyBucketCount];
850 void recordSyscall() {
851 __atomic_fetch_add(&m_Metadata.syscallCount,
static_cast<uint64_t
>(1), __ATOMIC_RELAXED);
855 void recordSyscallDuration(Time::Timestamp duration) {
857 Time::Timestamp limit = Time::Multiplier::Microsecond;
858 while (bucket + 1 < SyscallLatencyBucketCount && duration >= limit) {
862 __atomic_fetch_add(&m_Metadata.syscallLatencyBuckets[bucket],
static_cast<uint64_t
>(1),
866 uint64_t getSyscallCount()
const {
867 return __atomic_load_n(&m_Metadata.syscallCount, __ATOMIC_ACQUIRE);
870 uint64_t getReapedChildrenSyscallCount()
const {
871 return __atomic_load_n(&m_Metadata.reapedChildrenSyscallCount, __ATOMIC_ACQUIRE);
874 void getSyscallLatencySnapshot(SyscallLatencySnapshot& snapshot)
const {
875 for (
size_t i = 0; i < SyscallLatencyBucketCount; ++i) {
876 snapshot.buckets[i] =
877 __atomic_load_n(&m_Metadata.syscallLatencyBuckets[i], __ATOMIC_ACQUIRE) +
878 __atomic_load_n(&m_Metadata.reapedChildrenSyscallLatencyBuckets[i], __ATOMIC_ACQUIRE);
882 void getReapedChildrenSyscallLatencySnapshot(SyscallLatencySnapshot& snapshot)
const {
883 for (
size_t i = 0; i < SyscallLatencyBucketCount; ++i) {
884 snapshot.buckets[i] =
885 __atomic_load_n(&m_Metadata.reapedChildrenSyscallLatencyBuckets[i], __ATOMIC_ACQUIRE);
895 void accountReapedChild(
const Process* child, Time::Timestamp& user, Time::Timestamp& kernel);
897 Time::Timestamp getStartTime()
const {
898 return __atomic_load_n(&m_Metadata.startTime, __ATOMIC_ACQUIRE);
903 return __atomic_load_n(&m_Metadata.heapUsage, __ATOMIC_ACQUIRE);
905 ssize_t getVirtualPageCount()
const {
906 return __atomic_load_n(&m_Metadata.virtualPages, __ATOMIC_ACQUIRE);
908 ssize_t getPhysicalPageCount()
const {
909 return __atomic_load_n(&m_Metadata.physicalPages, __ATOMIC_ACQUIRE);
911 ssize_t getSharedPageCount()
const {
912 return __atomic_load_n(&m_Metadata.sharedPages, __ATOMIC_ACQUIRE);
920 return m_bSharedAddressSpace;
930 static void setInit(
Process* pProcess);
934 static bool loadFilesystemIds(
const Thread&, uint32_t& uid, uint32_t& gid);
935 static void publishFilesystemIds(
Thread&, uint32_t uid, uint32_t gid);
936 void publishAccountIdentity(
User*,
Group*);
946 FilesystemContextMode filesystemContext = FilesystemContextMode::Inherit,
947 bool emptyAddressSpace =
false,
ProcessType type = Stock);
952#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
957 void makeOrphanBeforePublicationForHostedTest();
966 void prepareForDestruction();
969 void enableTimeAccountingReports(
size_t initialInterest = ~
size_t(0));
972 void setTimeAccountingReportInterest(
size_t interest,
bool enabled);
975 void finishTermination(
bool abandonStack,
bool notifyParent)
NORETURN;
987 void drainDeferredTimeAccounting();
990 void closeDeferredTimeAccounting();
993 Time::Timestamp totalTime(CpuTimeMode mode)
const;
995 ALWAYS_INLINE void reportTimeAccounting(Time::Timestamp elapsed) {
998 if (__atomic_load_n(&m_TimeAccountingReportInterest, __ATOMIC_ACQUIRE) &&
999 __atomic_load_n(&m_bTimeAccountingReportsEnabled, __ATOMIC_ACQUIRE)) {
1000 queueTimeAccountingReport(elapsed);
1004 void queueTimeAccountingReport(Time::Timestamp elapsed);
1039 Process* m_pVforkOwner =
nullptr;
1046 bool m_bFilesystemContextReady;
1060 uint64_t m_UserReservationGeneration;
1062#if PEDIGREE_BENCHMARK_SYSCALL_TIMING
1063 bool m_BenchmarkSyscallTiming =
false;
1064 uint64_t m_SyscallTimingCalls[SyscallTimingSlotCount] = {};
1065 uint64_t m_SyscallTimingKernelNanoseconds[SyscallTimingSlotCount] = {};
1068#if PEDIGREE_BENCHMARK_SYSCALL_TRACE
1069 bool m_BenchmarkSyscallTrace =
false;
1072#if PEDIGREE_BENCHMARK_VM_DIAGNOSTICS
1073 bool m_BenchmarkVmDiagnostics =
false;
1074 uint64_t m_BenchmarkVmCounters[BenchmarkVmCounterCount] = {};
1149 void suspendInternal(
int stopSignal,
bool checkContinuationEpoch,
size_t continuationEpoch);
1152 void transitionToTerminating();
1168 bool m_bExecCommitted =
false;
1169 bool m_bExecExitForwarded =
false;
1170 size_t m_nThreadCreations = 0;
1218 bool terminatingThreadReapable(
Thread* pThread,
bool& wakeOwner);
1221 void publishTerminationStatus(
bool notifyParent);
1224 void publishTerminationReapable();
1227 void publishReaperClaim();
1230 bool beginThreadJoin();
1233 void endThreadJoin();
1236 bool beginExternalLease();
1239 void endExternalLease();
1242 void closeExternalLeaseAdmission();
1245 void drainExternalLeases();
1248 void releaseThreadLease(
Thread* thread);
1251 void installTerminalOwner(
Thread* owner);
1255#if PEDIGREE_SYSCALL_COUNTER
1263 reapedChildrenUserTime(0),
1264 reapedChildrenKernelTime(0),
1266 reapedChildrenSyscallCount(0),
1267 syscallLatencyBuckets{},
1268 reapedChildrenSyscallLatencyBuckets{},
1278 reapedChildrenUserTime(0),
1279 reapedChildrenKernelTime(0),
1295 Time::Timestamp kernelTime;
1301#if PEDIGREE_SYSCALL_COUNTER
1303 uint64_t syscallCount;
1305 uint64_t reapedChildrenSyscallCount;
1307 uint64_t syscallLatencyBuckets[SyscallLatencyBucketCount];
1309 uint64_t reapedChildrenSyscallLatencyBuckets[SyscallLatencyBucketCount];
1328 size_t m_TimeAccountingReportInterest;
1336#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
1337 static TerminationElectionHook m_TerminationElectionHook;
1338 static ExternalLeaseReleaseHook m_ExternalLeaseReleaseHook;
1339 static Process* m_ExternalLeaseReleaseTarget;
1340 static OrphanPublicationHook m_OrphanPublicationHook;