55 lines
2.0 KiB
C++
55 lines
2.0 KiB
C++
/*
|
|
* ApicTimer.hpp
|
|
* Local APIC timer for periodic tick interrupts and timekeeping
|
|
* Copyright (c) 2025 Daniel Hammer
|
|
*/
|
|
|
|
#pragma once
|
|
#include <cstdint>
|
|
|
|
namespace Timekeeping {
|
|
// Initialize the APIC timer: calibrate against PIT, start periodic interrupts
|
|
void ApicTimerInitialize();
|
|
|
|
// Initialize the scheduler timer on an AP using the BSP calibration.
|
|
void ApicTimerInitializeAP();
|
|
|
|
// Idle APs are woken for runnable work by the reschedule IPI, so their
|
|
// periodic scheduler timer can remain masked until a process is dispatched.
|
|
void ApicTimerEnterApIdle();
|
|
void ApicTimerLeaveApIdle();
|
|
|
|
// Reinitialize the APIC timer after S3 resume using the previously
|
|
// calibrated tick rate. Skips PIT calibration and IRQ registration
|
|
// (both survive in RAM). Only reprograms the timer hardware registers.
|
|
void ApicTimerReinitialize();
|
|
|
|
// Get the monotonic tick count (increments on each timer interrupt)
|
|
uint64_t GetTicks();
|
|
|
|
// Get elapsed milliseconds since timer initialization
|
|
uint64_t GetMilliseconds();
|
|
|
|
// Enable scheduler tick (called after scheduler is initialized)
|
|
void EnableSchedulerTick();
|
|
|
|
// Run bounded process-context bottom halves from an idle CPU.
|
|
void ServiceDeferredWork();
|
|
|
|
// Enter one idle wait cycle for the current CPU. Uses HLT and relies on
|
|
// the boot-time periodic LAPIC timer to wake -- one-shot wake doesn't
|
|
// survive deep C-states on some laptop CPUs.
|
|
void IdleOnce(bool hasMwait, volatile uint64_t* monitorAddr = nullptr);
|
|
|
|
// Busy-wait sleep for the given number of milliseconds
|
|
void Sleep(uint64_t ms);
|
|
|
|
// Spin for at least `ms` milliseconds without descheduling. Usable from
|
|
// boot code, before the scheduler runs, and with interrupts disabled
|
|
// (falls back to timed I/O port writes when the tick is not advancing).
|
|
void BusyWaitMs(uint64_t ms);
|
|
|
|
// Spin for at least `us` microseconds. Port-0x80 timed, so it errs long.
|
|
void BusyWaitUs(uint64_t us);
|
|
};
|