This commit is contained in:
2026-07-03 15:09:16 +01:00
parent df774691c8
commit 31bf86af56
12 changed files with 492 additions and 41 deletions
+19 -2
View File
@@ -46,8 +46,25 @@ it against the **PIT** (the legacy 8254, whose 1.193182 MHz is fixed): run the
LAPIC timer one-shot from its maximum count while the PIT counts out a known 10 ms
(polling channel 2, no interrupt needed), then see how far the LAPIC got. That
yields its counts-per-millisecond, from which `initTimer(hz)` computes the reload
count for any target frequency. danos runs it at **1000 Hz** (a 1 ms tick), and the
tick count times the known period gives a monotonic `uptimeMs()`.
count for any target frequency. danos runs it at **1000 Hz** (a 1 ms tick).
## The high-resolution clock (TSC)
The timer tick gives *scheduling* — a 1 ms quantum — but 1 ms is coarse for a
real-time system to *measure* with (interrupt latency, jitter, timeouts). So the
same calibration also measures the **TSC** (Time Stamp Counter): a per-core cycle
counter read with `rdtsc` in a couple of cycles, giving roughly **nanosecond**
resolution — a million times finer than the tick. We snapshot the TSC across the
same 10 ms PIT window to get its frequency (measured ~3.6 GHz on the test host).
The monotonic clock is exposed as one function per resolution — `nanos()`,
`micros()`, `millis()` — each scaling the cycle delta directly at its unit (with a
128-bit intermediate so a long uptime doesn't overflow) rather than chaining
divisions. `millis()` is what the scheduler uses for `sleep` deadlines; `nanos()`
is there for fine measurement. Note the two clocks are distinct: the **tick** drives
preemption and wakeups (1 ms granularity); the **TSC** is the resolution you read
time at. Making `sleep` itself sub-millisecond would take a tickless one-shot
timer — a later step.
## Two kinds of vector, one dispatch