9#ifndef PEDIGREE_KERNEL_ACTIVITYDIAGNOSTICS_H
10#define PEDIGREE_KERNEL_ACTIVITYDIAGNOSTICS_H
12#include "pedigree/kernel/compiler.h"
18namespace ActivityDiagnostics {
20static constexpr size_t DurationBucketCount = 16;
21static constexpr size_t InterruptVectorCount = 256;
22static constexpr size_t UserReturnSamplePeriod = 64;
23static constexpr size_t UserEntrySamplePeriod = 256;
25enum class UserReturnStage :
size_t {
41static constexpr size_t UserReturnStageCount =
static_cast<size_t>(UserReturnStage::Count);
45 uint64_t interruptCount;
46 uint64_t exceptionCount;
47 uint64_t hardwareInterruptCount;
48 uint64_t otherInterruptCount;
49 uint64_t interruptVectorCounts[InterruptVectorCount];
50 uint64_t interruptDurationBuckets[DurationBucketCount];
51 uint64_t pageFaultDurationBuckets[DurationBucketCount];
52 uint64_t schedulerTimerDurationBuckets[DurationBucketCount];
53 uint64_t hardDispatchCount;
54 uint64_t hardDurationBuckets[DurationBucketCount];
55 uint64_t threadedDispatchCount;
56 uint64_t threadedDurationBuckets[DurationBucketCount];
57 uint64_t schedulerTimerTicks;
58 uint64_t scheduleCalls;
59 uint64_t sameThreadSelections;
60 uint64_t contextSwitches;
61 uint64_t idleSelections;
62 uint64_t schedulerIdleFallbacks;
63 uint64_t schedulerIdleFallbackCurrentReady;
64 uint64_t schedulerIdleFallbackCurrentPending;
65 uint64_t schedulerNoEligibleSelections;
66 uint64_t readyQueueScanEntries;
67 uint64_t readyQueueCandidateVisits;
68 uint64_t readyQueuePredicateRejects;
69 uint64_t readyQueueSelectionSamples;
70 uint64_t readyQueueSelectionDurationBuckets[DurationBucketCount];
71 uint64_t timeAccountingSamples;
72 uint64_t timeAccountingDurationBuckets[DurationBucketCount];
73 uint64_t idleHaltEntries;
74 uint64_t framebufferFlips;
75 uint64_t framebufferCells;
76 uint64_t framebufferDurationBuckets[DurationBucketCount];
77 uint64_t userReturnStageSamples[UserReturnStageCount];
78 uint64_t userReturnStageTotalNanoseconds[UserReturnStageCount];
79 uint64_t userReturnStageDurationBuckets[UserReturnStageCount][DurationBucketCount];
80 uint64_t userReturnFaultHandledSamples;
81 uint64_t userReturnFaultFallbackSamples;
82 uint64_t userReturnInterruptAffinityWaitedSamples;
83 uint64_t userReturnSyscallAffinityWaitedSamples;
84 uint64_t userEntryCaptureCalls;
85 uint64_t userEntryRestoreCalls;
86 uint64_t userEntryCaptureSamples;
87 uint64_t userEntryRestoreSamples;
88 uint64_t userEntryCaptureTscTotal;
89 uint64_t userEntryRestoreTscTotal;
90 uint64_t userEntryEmptyTscSamples;
91 uint64_t userEntryEmptyTscTotal;
92 uint64_t userEntryCaptureTscBuckets[DurationBucketCount];
93 uint64_t userEntryRestoreTscBuckets[DurationBucketCount];
94 uint64_t userEntryEmptyTscBuckets[DurationBucketCount];
97#if PEDIGREE_ACTIVITY_DIAGNOSTICS
99EXPORTED_PUBLIC uint64_t timestamp();
100EXPORTED_PUBLIC
void snapshot(
Snapshot& result);
102void recordInterruptEntry(
size_t vector);
103void recordInterruptDuration(
size_t vector, uint64_t duration);
104void recordHardDispatch(uint8_t irq, uint64_t duration);
105void recordThreadedDispatch(uint8_t irq, uint64_t duration);
106void recordSchedulerTimer();
107void recordScheduleCall();
108void recordSameThreadSelection();
109void recordContextSwitch();
110void recordIdleSelection();
111void recordSchedulerIdleFallback(
bool currentReady,
bool currentPending);
112void recordSchedulerNoEligibleSelection();
113void recordReadyQueueScanEntry();
114void recordReadyQueueCandidateVisit();
115void recordReadyQueuePredicateReject();
116bool shouldSampleReadyQueueSelection();
117void recordReadyQueueSelection(uint64_t duration);
118bool shouldSampleTimeAccounting();
119void recordTimeAccounting(uint64_t duration);
120void recordIdleHalt();
121EXPORTED_PUBLIC
void recordFramebufferFlip(
size_t cells, uint64_t duration);
122void recordUserReturnStage(UserReturnStage stage, uint64_t duration);
123void recordUserReturnFaultOutcome(
bool handled);
124void recordUserReturnAffinityWait(
bool syscall);
128 explicit InterruptScope(
size_t vector) : m_Vector(vector), m_Start(timestamp()) {
129 recordInterruptEntry(vector);
133 recordInterruptDuration(m_Vector, timestamp() - m_Start);
141class HardDispatchScope {
143 explicit HardDispatchScope(uint8_t irq) : m_Irq(irq), m_Start(timestamp()) {}
145 ~HardDispatchScope() {
146 recordHardDispatch(m_Irq, timestamp() - m_Start);
154class ReadyQueueSelectionScope {
156 ReadyQueueSelectionScope()
157 : m_Active(shouldSampleReadyQueueSelection()), m_Start(m_Active ? timestamp() : 0) {}
159 ~ReadyQueueSelectionScope() {
161 recordReadyQueueSelection(timestamp() - m_Start);
169class TimeAccountingScope {
171 TimeAccountingScope()
172 : m_Active(shouldSampleTimeAccounting()), m_Start(m_Active ? timestamp() : 0) {}
174 ~TimeAccountingScope() {
176 recordTimeAccounting(timestamp() - m_Start);
186inline uint64_t timestamp() {
190inline void snapshot(Snapshot& result) {
194inline void recordInterruptEntry(
size_t) {}
195inline void recordInterruptDuration(
size_t, uint64_t) {}
196inline void recordHardDispatch(uint8_t, uint64_t) {}
197inline void recordThreadedDispatch(uint8_t, uint64_t) {}
198inline void recordSchedulerTimer() {}
199inline void recordScheduleCall() {}
200inline void recordSameThreadSelection() {}
201inline void recordContextSwitch() {}
202inline void recordIdleSelection() {}
203inline void recordSchedulerIdleFallback(
bool,
bool) {}
204inline void recordSchedulerNoEligibleSelection() {}
205inline void recordReadyQueueScanEntry() {}
206inline void recordReadyQueueCandidateVisit() {}
207inline void recordReadyQueuePredicateReject() {}
208inline bool shouldSampleReadyQueueSelection() {
211inline void recordReadyQueueSelection(uint64_t) {}
212inline bool shouldSampleTimeAccounting() {
215inline void recordTimeAccounting(uint64_t) {}
216inline void recordIdleHalt() {}
217inline void recordFramebufferFlip(
size_t, uint64_t) {}
218inline void recordUserReturnStage(UserReturnStage, uint64_t) {}
219inline void recordUserReturnFaultOutcome(
bool) {}
220inline void recordUserReturnAffinityWait(
bool) {}