2#include "pedigree/kernel/LockGuard.h"
3#include "pedigree/kernel/process/PerProcessorScheduler.h"
4#include "pedigree/kernel/process/Scheduler.h"
5#include "pedigree/kernel/process/Thread.h"
6#include "pedigree/kernel/processor/Processor.h"
7#include "pedigree/kernel/time/Time.h"
8#include "pedigree/kernel/utilities/Pointers.h"
18 for (
size_t i = 0; i < count; ++i)
19 Scheduler::releaseActivityEntry(entries.get()[i].process, entries.get()[i].thread);
26void Scheduler::releaseActivityEntry(
Process* process,
Thread* thread) {
34 SystemActivity result;
38 if (it.key() != __atomic_load_n(&it.value()->m_pIdleThread, __ATOMIC_ACQUIRE))
44 m_LoadAverage.snapshot(result.loads);
46 result.userNanoseconds = m_UserNanoseconds;
47 result.kernelNanoseconds = m_KernelNanoseconds;
48 result.idleNanoseconds = m_IdleNanoseconds;
54 if (owner && &thread == __atomic_load_n(&owner->m_pIdleThread, __ATOMIC_ACQUIRE)) {
55 m_IdleNanoseconds += elapsed;
56 }
else if (mode == CpuTimeMode::User) {
57 m_UserNanoseconds += elapsed;
59 m_KernelNanoseconds += elapsed;
64 if (Time::getTicks() < __atomic_load_n(&m_NextActivityAttempt, __ATOMIC_ACQUIRE))
67 if (__atomic_compare_exchange_n(&m_ActivitySamplePending, &pending,
true,
false, __ATOMIC_ACQ_REL,
75 __atomic_store_n(&m_ActivitySamplePending,
false, __ATOMIC_RELEASE);
76 const uint64_t now = Time::getTicks();
77 if (now < __atomic_load_n(&m_NextActivityAttempt, __ATOMIC_ACQUIRE))
80 if (now < m_NextActivityAttempt)
82 const uint64_t delay = LoadAverage::PeriodNanoseconds;
83 __atomic_store_n(&m_NextActivityAttempt, now > ~uint64_t(0) - delay ? ~uint64_t(0) : now + delay,
87 bool prepared =
false;
88 for (
unsigned attempt = 0; attempt < 4; ++attempt) {
95 if (required && !sample.entries)
102 Thread* thread = it.key();
103 if (thread == __atomic_load_n(&it.value()->m_pIdleThread, __ATOMIC_ACQUIRE))
108 auto& entry = sample.entries.get()[sample.count++];
109 entry.process = process;
111 entry.thread = thread;
121 for (
size_t i = 0; i < sample.count; ++i) {
122 Thread* thread = sample.entries.get()[i].thread;
123 if (!thread || thread == observer)
129 if ((status == Thread::Ready || status == Thread::Running) &&
130 !__atomic_load_n(&thread->m_ReadyPublicationPending, __ATOMIC_ACQUIRE))
131 if (active != ~uint32_t(0))
135 m_LoadAverage.update(now, active);
138#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
139bool Scheduler::runHostedLoadAverageRequestRegression() {
141 const uint64_t deadline = __atomic_load_n(&m_NextActivityAttempt, __ATOMIC_ACQUIRE);
142 if (Time::getTicks() >= deadline)
146 __atomic_store_n(&m_ActivitySamplePending,
true, __ATOMIC_RELEASE);
148 return !__atomic_load_n(&m_ActivitySamplePending, __ATOMIC_ACQUIRE) &&
149 __atomic_load_n(&m_NextActivityAttempt, __ATOMIC_ACQUIRE) == deadline;
bool beginExternalLease()
static ProcessorInformation & information()
void recordCpuTime(const Thread &thread, CpuTimeMode mode, Time::Timestamp elapsed)
void requestLoadAverageSample()
Tree< Thread *, PerProcessorScheduler * > m_TPMap
Process * getParent() const
class PerProcessorScheduler * getScheduler() const
bool beginExternalLease()