131 lines
5.1 KiB
C
131 lines
5.1 KiB
C
// Kernel ke sched declarations shared by implementation files and kernel clients.
|
|
|
|
#pragma once
|
|
#include <stdbool.h>
|
|
// The scheduler combines dynamic normal queues with static real-time queues.
|
|
// Per-processor timer IRQs drive KeSchedulerTick.
|
|
#include <kernel/ke_thread.h>
|
|
|
|
struct KCPU;
|
|
|
|
#define SCHED_TICK_MS 10u
|
|
#define SCHED_REALTIME_QUANTUM_TICKS 1u
|
|
#define SCHED_HIGH_QUANTUM_TICKS 2u
|
|
#define SCHED_NORMAL_QUANTUM_TICKS 4u
|
|
#define SCHED_LOW_QUANTUM_TICKS 8u
|
|
#define SCHED_DEMOTE_AFTER_BURST_TICKS 16u
|
|
#define SCHED_AGING_INTERVAL_TICKS 100u
|
|
#define KE_PRIORITY_INHERITANCE_MAX_DEPTH 64u
|
|
|
|
typedef struct KE_SCHED_STATS {
|
|
uint64_t Ticks;
|
|
uint64_t ContextSwitches;
|
|
uint64_t KeepCurrentDecisions;
|
|
uint64_t IdleSelections;
|
|
uint64_t Demotions;
|
|
uint64_t AgingPromotions;
|
|
uint64_t QuantumExpirations;
|
|
uint64_t PriorityPreemptions;
|
|
uint64_t VoluntaryBlocks;
|
|
uint64_t CpuBurstDemotions;
|
|
uint64_t SmtSiblingDeferrals;
|
|
uint64_t SmtPrimaryPokes;
|
|
uint64_t RealtimeDispatches;
|
|
uint64_t RealtimePreemptions;
|
|
uint64_t PriorityInheritanceBoosts;
|
|
uint64_t PriorityInheritanceDrops;
|
|
uint64_t PriorityInheritancePropagations;
|
|
uint64_t PriorityInheritanceMaxDepth;
|
|
} KE_SCHED_STATS;
|
|
|
|
|
|
struct MUTEX;
|
|
|
|
typedef struct KE_THREAD_SCHEDULER_SNAPSHOT {
|
|
THREAD_STATE State;
|
|
KE_SCHEDULING_CLASS BaseSchedulingClass;
|
|
uint32_t BasePriority;
|
|
KE_SCHEDULING_CLASS EffectiveSchedulingClass;
|
|
uint32_t EffectivePriority;
|
|
uint32_t RunningCpu;
|
|
uint32_t LastCpu;
|
|
uint32_t QuantumRemaining;
|
|
uint32_t QuantumTicks;
|
|
uint32_t CpuBurstTicks;
|
|
uint32_t LastRunTicks;
|
|
uint32_t WaitObjectType;
|
|
KSTATUS WaitStatus;
|
|
struct MUTEX* WaitingMutex;
|
|
bool Queued;
|
|
bool AlertableWait;
|
|
} KE_THREAD_SCHEDULER_SNAPSHOT;
|
|
|
|
// Copies scheduler-owned thread state into a stable diagnostic snapshot.
|
|
void KiSchedulerSnapshotThread(THREAD* thread, KE_THREAD_SCHEDULER_SNAPSHOT* snapshot);
|
|
|
|
// Selects waiters and refreshes donations while the mutex lock is held.
|
|
struct THREAD* KiSchedulerSelectMutexWaiter(struct MUTEX* mutex);
|
|
bool KiSchedulerRefreshMutexDonation(struct MUTEX* mutex);
|
|
|
|
// Updates one thread's normal-class base priority.
|
|
KSTATUS KiSchedulerSetNormalPriority(THREAD* thread, THREAD_PRIORITY priority);
|
|
|
|
// Publishes one mutex dependency atomically with cycle detection.
|
|
KSTATUS KiSchedulerPrepareMutexWait(THREAD* thread, struct MUTEX* mutex, THREAD* owner);
|
|
void KiSchedulerCancelMutexWait(THREAD* thread, struct MUTEX* mutex);
|
|
|
|
// Associates mutex ownership with priority-inheritance bookkeeping.
|
|
void KiSchedulerAcquireMutexOwnership(THREAD* thread, struct MUTEX* mutex);
|
|
void KiSchedulerTransferMutexOwnership(THREAD* oldOwner, THREAD* newOwner,
|
|
struct MUTEX* mutex);
|
|
void KiSchedulerReleaseMutexOwnership(THREAD* thread, struct MUTEX* mutex);
|
|
struct MUTEX* KiSchedulerFirstOwnedMutex(THREAD* thread);
|
|
void KiSchedulerNotePriorityPropagation(uint32_t depth);
|
|
|
|
// Recomputes effective rank and optionally returns a referenced upstream mutex.
|
|
bool KiSchedulerRefreshEffectivePriority(THREAD* thread, struct MUTEX** waitingMutexOut);
|
|
|
|
// Called once by KernelMain before any threads are created.
|
|
void KeInitializeScheduler(void);
|
|
|
|
// Split global scheduler setup from per-CPU idle-thread creation so AP bring-up
|
|
// can add one idle thread per CPU without reinitializing the global queues.
|
|
void KiInitializeSchedulerGlobal(void);
|
|
KSTATUS KiCreateIdleThreadForCpu(struct KCPU* cpu);
|
|
|
|
// Add / remove a thread from the run queues.
|
|
void KeReadyThread(THREAD* thread);
|
|
void KeUnreadyThread(THREAD* thread);
|
|
|
|
// Called from each CPU timer ISR every SCHED_TICK_MS. Every CPU performs local
|
|
// quantum accounting and may request a local reschedule. Only the boot processor advances
|
|
// global scheduler time and services sleepers, waitable timers, input repeat,
|
|
// and priority aging. The actual context switch happens from KiExitInterrupt
|
|
// after the IRQ handler has returned and EOI has been sent.
|
|
void KeSchedulerTick(void);
|
|
|
|
// Internal scheduler hooks used by the interrupt-exit path. KiRequestReschedule
|
|
// is cheap and can be called from interrupt context. KiScheduleFromInterrupt
|
|
// consumes the pending request and performs the context switch, if needed.
|
|
void KiRequestReschedule(void);
|
|
bool KiIsReschedulePending(void);
|
|
void KiScheduleFromInterrupt(void);
|
|
void KiSchedulerNoteVoluntaryBlock(THREAD* thread);
|
|
void KiSchedulerMarkThreadWaiting(THREAD* thread);
|
|
void KiSchedulerWakeThread(THREAD* thread, KSTATUS status);
|
|
|
|
// Blocks the current thread until at least the requested delay has elapsed.
|
|
__declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds);
|
|
KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus);
|
|
|
|
// Voluntarily yield the CPU. Picks the next runnable thread immediately.
|
|
__declspec(dllexport) void KeYield(void);
|
|
|
|
void KeGetSchedulerStats(KE_SCHED_STATS* out);
|
|
|
|
// Returns the thread currently running on this CPU.
|
|
THREAD* KeGetCurrentThread(void);
|
|
|
|
// Set the current thread for the current CPU. Used during CPU/scheduler bring-up.
|
|
void KeSetCurrentThread(THREAD* thread);
|