23#include "pedigree/kernel/ActivityDiagnostics.h"
24#include "pedigree/kernel/LockGuard.h"
25#include "pedigree/kernel/process/RoundRobin.h"
26#include "pedigree/kernel/process/Thread.h"
27#include "pedigree/kernel/processor/Processor.h"
28#include "pedigree/kernel/processor/types.h"
29#include "pedigree/kernel/utilities/assert.h"
32 for (
size_t i = 0; i < MAX_PRIORITIES; ++i) {
33 m_pReadyQueueHeads[i] =
nullptr;
34 m_pReadyQueueTails[i] =
nullptr;
35#if PEDIGREE_READY_QUEUE_COUNTS
36 m_ReadyQueueCounts[i] = 0;
42 for (
size_t i = 0; i < MAX_PRIORITIES; ++i) {
43 while (m_pReadyQueueHeads[i]) {
44 unlink(m_pReadyQueueHeads[i]);
46 assert(!m_pReadyQueueTails[i]);
57void RoundRobin::enqueue(
Thread* pThread) {
59 assert(isReady(pThread));
60 assert(!pThread->m_bReadyQueued);
62 assert(!pThread->m_pReadyNext);
63 assert(pThread->getPriority() < MAX_PRIORITIES);
65 const size_t priority = pThread->getPriority();
67 pThread->m_ReadyQueuePriority = priority;
68 pThread->m_bReadyQueued =
true;
69 if (m_pReadyQueueTails[priority]) {
70 m_pReadyQueueTails[priority]->m_pReadyNext = pThread;
72 m_pReadyQueueHeads[priority] = pThread;
74 m_pReadyQueueTails[priority] = pThread;
75#if PEDIGREE_READY_QUEUE_COUNTS
76 ++m_ReadyQueueCounts[priority];
80void RoundRobin::unlink(
Thread* pThread) {
81 if (!pThread || !pThread->m_bReadyQueued) {
85 const size_t priority = pThread->m_ReadyQueuePriority;
86 assert(priority < MAX_PRIORITIES);
90 assert(m_pReadyQueueHeads[priority] == pThread);
91 m_pReadyQueueHeads[priority] = pThread->m_pReadyNext;
93 if (pThread->m_pReadyNext) {
96 assert(m_pReadyQueueTails[priority] == pThread);
101 pThread->m_pReadyNext =
nullptr;
102 pThread->m_ReadyQueuePriority = MAX_PRIORITIES;
103 pThread->m_bReadyQueued =
false;
104#if PEDIGREE_READY_QUEUE_COUNTS
105 assert(m_ReadyQueueCounts[priority]);
106 --m_ReadyQueueCounts[priority];
115 for (
size_t i = 0; i < MAX_PRIORITIES; i++) {
117#if PEDIGREE_READY_QUEUE_COUNTS
120 size_t candidates = m_ReadyQueueCounts[i];
124 size_t candidates = 0;
125 for (pThread = m_pReadyQueueHeads[i]; pThread; pThread = pThread->m_pReadyNext)
128 while (candidates--) {
129 pThread = m_pReadyQueueHeads[i];
131 ActivityDiagnostics::recordReadyQueueCandidateVisit();
134 if (pThread == pCurrentThread || !isReady(pThread)) {
138 if (pThread->getPriority() != i) {
146 ActivityDiagnostics::recordSchedulerNoEligibleSelection();
152 for (
size_t i = 0; i < MAX_PRIORITIES; ++i) {
153 if (m_pReadyQueueHeads[i]) {
163 if (pThread->m_bReadyQueued) {
164 if (!RoundRobin::isReady(pThread) || pThread->m_ReadyQueuePriority != pThread->getPriority()) {
171 if (RoundRobin::isReady(pThread)) {
176bool RoundRobin::isReady(
Thread* pThread) {
177 return pThread->
getStatus() == Thread::Ready &&
178 !__atomic_load_n(&pThread->m_ReadyPublicationPending, __ATOMIC_ACQUIRE);
181#if HOSTED && PEDIGREE_HOSTED_SMOKE_TESTS
182bool RoundRobin::runHostedIntrusiveQueueRegressions(
Thread* pThread) {
183 if (!pThread || pThread->m_bReadyQueued || pThread->
m_pReadyPrevious || pThread->m_pReadyNext) {
199 passed &= pThread->m_bReadyQueued && pThread->m_ReadyQueuePriority == 1 &&
204 passed &= pThread->m_bReadyQueued && pThread->m_ReadyQueuePriority == 2 &&
207 pThread->
m_Status = Thread::AwaitingJoin;
208 passed &= !queue.
getNext(
nullptr) && !pThread->m_bReadyQueued;
212 passed &= !queue.
getNext(pThread) && !pThread->m_bReadyQueued;
216 passed &= pThread->m_bReadyQueued;
219 passed &= !pThread->m_bReadyQueued && !pThread->
m_pReadyPrevious && !pThread->m_pReadyNext &&
220 pThread->m_ReadyQueuePriority == MAX_PRIORITIES;
226 passed &= reused.
getNext(
nullptr) == pThread && !pThread->m_bReadyQueued;
static bool getInterrupts()
static void setInterrupts(bool bEnable)
virtual void threadStatusChanged(Thread *pThread)
virtual void addThread(Thread *pThread)
virtual Thread * getNext(Thread *pCurrentThread)
virtual void removeThread(Thread *pThread)
Thread * m_pReadyPrevious