fix(timekeeping): restore monotonic clock and clocksource semantics#2145
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a4fcef6048
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fc6035d031
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
|
Codex Review: Didn't find any major issues. Swish! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10d4cdf03c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 789969b9b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Fixed the Dunitest PTY hang in 9343de6.\n\nRoot causes addressed:\n- nanosleep could lose a timer wakeup before the task entered the blocked state;\n- N_TTY recursively acquired the writer-preferred termios lock and synchronously re-entered the line discipline while holding receive-path locks.\n\nValidation on 2 vCPUs:\n- ByteStream PTY regression: 200/200 passes;\n- CubeSandbox PTY suite: 27/27 passes;\n- timekeeping semantics: 15/15 passes (2 opt-in stress tests skipped);\n- restart syscall semantics: 3/3 passes;\n- ClockNanosleepRelativeAndAbsoluteDomains: 10/10 passes.\n\n@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9343de6c14
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| match clockid { | ||
| Realtime | Monotonic | Boottime | ProcessCPUTimeID | ThreadCPUTimeID => {} | ||
| Realtime | Monotonic | Boottime | ProcessCPUTimeID => {} | ||
| ThreadCPUTimeID => return Err(SystemError::EINVAL), |
There was a problem hiding this comment.
在绕过 libc 直接使用 SYS_clock_nanosleep(CLOCK_THREAD_CPUTIME_ID, ...) 的场景下,这个 clock id 是有效的 POSIX clock,但内核不支持对它执行 nanosleep;Linux 内核的原始 syscall 对这类“有效但无 nsleep 操作”的 clock 返回 ENOTSUP/EOPNOTSUPP,而这里返回 EINVAL 会让直接 syscall 用户和系统调用兼容性测试观察到错误的 errno(glibc 的 clock_nanosleep() 包装层可能提前返回 EINVAL,但不能替代 syscall 层语义)。
Useful? React with 👍 / 👎.
DragonOS used the realtime epoch as the basis for monotonic clocks and spread clocksource cycle state across multiple owners. The resulting updates could lose elapsed time, recurse through the timekeeper lock, and make timeout consumers depend on wall-clock adjustments. KVM clock CPU bring-up and interrupt-context locking also lacked transactional failure handling. Rework the timekeeping core around independently maintained monotonic and raw read bases, with realtime and boottime represented as offsets. Keep clocksource selection, watchdog state, switching, and rollback under a single control transaction, and preserve elapsed time and fractional state when a source changes. Make KVM clock setup per-CPU and transactional, including AP failure rollback. Add writer-preferred RwLock progress and explicit interrupt context tracking so timekeeper writers cannot deadlock behind continuous readers or acquire blocking paths from hardirq/softirq context. Align POSIX clock reads, nanosleep restart handling, signal waits, and futex timeouts with their Linux clock domains. Add kernel selftests, dunitest coverage, a guest calibration workload, and a fail-closed host calibration harness for KVM and TCG evidence. Validation: - x86_64 kernel build and link - RISC-V Rust build and kernel ELF link - 31 host calibration unit tests - guest calibration workload static build - QEMU runner and Python syntax checks - KVM 2-vCPU timekeeping/restart suite: 19/19 relevant tests passed - fixed-CPU and migrating 10,000,000-read monotonicity tests passed Signed-off-by: longjin <longjin@dragonos.org>
Serialize watchdog cleanup with clocksource registration and fully roll back partially published watchdog state. Keep hardirq nesting counters cache-line isolated and avoid the CAS loop on interrupt entry and exit. Match Linux's settimeofday boundary after suspend, expose clocksource selftests through debugfs, and bound normal guest semantic loops while retaining the opt-in ten-million-read stress gates. Make QEMU argv evidence fail closed, release partially initialized serial transport resources, and resolve the formatting regressions reported by CI. Validated with make fmt, make kernel, host calibration tests, the calibration host build, and DragonOS guest timekeeping selftest and semantics suites. Signed-off-by: longjin <longjin@dragonos.org>
Restore preemption when an already-registered rwlock writer acquisition fails, and cover the failure path in the debugfs selftest. Consolidate all selftest-only registered writer attempts behind the balanced helper. Also preserve the underlying serial socket error in calibration diagnostics and verify both the reported detail and resource cleanup. Validated with format and Clippy checks, the kernel build, calibration unit and host tests, and DragonOS guest timekeeping selftests. Signed-off-by: longjin <longjin@dragonos.org>
Network polling walked the bound-socket vector by index while dropping the lock around every notification. Concurrent socket teardown could remove an earlier entry, shift the vector, and make the next index skip a poll waiter entirely. Take one coherent Arc snapshot and reuse the shared notification path for regular polling, NAPI polling, and listener teardown. Notifications still run outside the bounds lock, preserving the required lock order, while a single read-side acquisition avoids writer-fair reacquisition stalls under close-heavy workloads. This prevents tcp_close_semantics poll timeouts during concurrent IPv4 and dual-stack reset/close stress. Signed-off-by: longjin <longjin@dragonos.org>
Kernel stack allocation and reclamation used try_lock_irqsave().unwrap() on their shared mapper lock. Concurrent fork and exit activity therefore converted ordinary lock contention into a kernel panic, as observed when tcp_socket_test created processes on both CPUs. Acquire KSTACK_LOCK with the blocking irqsave spin-lock operation in both paths. This preserves the existing mapper serialization and interrupt exclusion while allowing the contending CPU to wait for the current stack operation to finish. The gVisor tcp_socket_test now completes all 184 tests without triggering the allocation race. Signed-off-by: longjin <longjin@dragonos.org>
Make the network interface's bound-socket table copy-on-write. Poll and notification paths now clone only the outer Arc while interrupts are disabled, while the less frequent bind and unbind paths perform any required Vec clone. This preserves a coherent notification snapshot without O(n) IRQ-off allocation or the index-shift race fixed earlier. Use one by-value termios snapshot for each N_TTY receive batch and pass it through the nested input helpers. The previous receive path recursively acquired the same read lock; once a termios writer queued, writer-fair admission blocked the recursive reader and deadlocked both CPUs. A value snapshot preserves consistent per-batch input semantics and removes the recursive locking dependency. Validated with make kernel, all 27 CubeSandbox PTY exec-chain tests, and all 6 TCP close semantics tests. Signed-off-by: longjin <longjin@dragonos.org>
Apply the repository rustfmt output required by the architecture format-check jobs. No behavior changes. Signed-off-by: longjin <longjin@dragonos.org>
Treat HPET enablement as a hardware transaction. If any validation, counter check, timer lookup, or IRQ registration step fails, restore the firmware general configuration instead of relying on the enabled flag, which is intentionally published only after IRQ setup succeeds. Snapshot and restore each timer comparator together with its configuration. Restore timer state while the counter is disabled, then write the complete firmware general configuration last so a firmware-enabled counter resumes only after all timer registers are coherent. Normal HPET disable now reuses the same restoration path. Validated with the repository format and Clippy checks, make kernel, and a DragonOS x86_64 fallback boot with HPET unavailable. Signed-off-by: longjin <longjin@dragonos.org>
Use a persistent waiter notification for nanosleep timers, preserve deadline semantics across signal and restart races, and avoid recursive N_TTY termios, flow, and line-discipline wakeup locking during input processing. This fixes the ByteStream PTY deadlocks observed in CI while keeping absolute sleeps from returning before their POSIX clock deadline. Signed-off-by: longjin <longjin@dragonos.org>
Signed-off-by: longjin <longjin@dragonos.org>
Signed-off-by: longjin <longjin@dragonos.org>
f64a17f to
a96bd95
Compare
|
@codex review |
|
Codex Review: Didn't find any major issues. Keep it up! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Signed-off-by: longjin <longjin@dragonos.org>
Summary
Root cause
The previous timekeeper used the realtime epoch for clocks that must remain independent of wall-clock changes. Clocksource cycle state also had multiple owners, so updates and source changes could lose elapsed time or recurse through the timekeeper lock. Continuous readers could starve writers, and KVM clock/AP initialization could expose partially initialized per-CPU state after a failure.
Timeout consumers inherited these clock-domain errors, making relative waits and restart handling sensitive to realtime behavior.
Implementation
The timekeeper now owns independent monotonic and raw read bases. Realtime and boottime are derived through explicit offsets, while coarse clocks expose committed bases without performing a hardware read.
Clocksource control operations use a single serialized transaction with validation and rollback. A switch forwards the old source before installing the new source, retains fractional time, and publishes one coherent generation. KVM clock setup preallocates per-CPU state and only marks an AP online after initialization succeeds.
RwLock writer preference provides bounded writer progress. Explicit interrupt-context guards keep blocking lock paths out of hardirq and softirq execution. POSIX clock syscalls and timeout users now select the clock domain required by Linux semantics.
User-visible impact
CLOCK_REALTIMEremains an epoch clock while monotonic/raw/boottime report uptime domains.This PR establishes the trustworthy Timekeeping baseline for later scheduler latency investigation; it does not claim to fix the separate
lat_ctxscheduling/wakeup performance issue.Validation
make kernel— x86_64 build and link passedmake -C kernel all ARCH=riscv64— Rust build and kernel ELF links passed; final local packaging could not run because the optional DragonStub checkout was unavailablepython3 -m unittest tools.timekeeping.test_calibrate— 31/31 passedmake -C user/apps/timekeeping_calibration test-host— passed with static linking and warnings-as-errorsbash -n tools/run-qemu.sh— passed