Skip to content

tracking(rcu): harden DragonOS RCU and close Linux 6.6 mechanism gaps #2208

Description

@fslongjin

Summary

This tracking issue coordinates the work required to turn DragonOS's current RCU implementation into a production-ready kernel synchronization subsystem, using Linux 6.6 semantics and mechanisms as the reference.

DragonOS already has a useful non-preemptible ordinary RCU foundation:

  • nested rcu_read_lock() / rcu_read_unlock();
  • grace-period tracking with an online-CPU bitmap;
  • call_rcu_raw(), deferred closures, and deferred drops;
  • synchronize_rcu() and rcu_barrier();
  • scheduler, user-return, idle, IRQ, and partial CPU-offline integration;
  • Rust-oriented RcuArcSlot and RcuOptionArcSlot;
  • debugfs self-tests and a guest dunitest.

However, RCU now protects task credentials and namespaces, signal state, network namespaces, packet sockets, and uprobe/BPF snapshots. It therefore needs stronger correctness guarantees, forward-progress mechanisms, architecture integration, diagnostics, and stress coverage before more kernel subsystems depend on it.

The near-term goal is not to copy all of Linux Tree RCU. The first goal is to make DragonOS's ordinary non-preemptible RCU correct, allocation-free in its core callback path, diagnosable, and testable. Additional RCU flavors should then be introduced only when their semantics have real consumers.

Current implementation

The production implementation is now organized around:

  • kernel/src/rcu/mod.rs
  • kernel/src/rcu/gp.rs
  • kernel/src/rcu/context.rs
  • kernel/src/rcu/callback.rs
  • kernel/src/rcu/progress.rs
  • kernel/src/rcu/selftest.rs
  • kernel/src/rcu/torture.rs
  • kernel/src/debug/rcu.rs
  • architecture entry/exit and CPU-hotplug integration under kernel/src/arch/, kernel/src/exception/, and kernel/src/smp/
  • user/apps/tests/dunitest/suites/normal/rcu_selftest.cc
  • user/apps/tests/dunitest/suites/normal/rcu_torture.cc

The current design uses a deterministic grace-period state machine with a flat holdout bitmap, persistent per-CPU context tracking, an RCU-owned participating-CPU lifecycle, and per-CPU intrusive callback queues segmented into done, wait, next-ready, and next. Raw callback admission is allocation-free; allocating deferred closures remain a task-context convenience API. Bounded callback execution, soft quiescent-state requests, reschedule-IPI escalation, stall reporting, debugfs statistics, deterministic self-tests, and seeded SMP torture coverage are implemented.

Completed subissues

All implementation subissues currently attached to this tracking issue are complete:

The remaining unchecked items below are follow-up validation or future API/flavor work not completed by those subissues.

Near-term work

The following items are the immediate scope of this tracking issue. Individual major items should normally be implemented as separate PRs and linked here.

1. Define the ordinary RCU contract and context model

  • Document DragonOS's ordinary RCU as non-preemptible and non-sleepable.
  • Define grace-period, publish/subscribe, callback, and barrier invariants.
  • Document the required happens-before chain across a complete grace period.
  • Introduce one architecture-neutral context-tracking state model for kernel, user, idle, IRQ, and NMI nesting.
  • Represent user and idle extended quiescent states persistently rather than as one-shot notifications.
  • Make architecture entry/exit hooks paired and auditable on x86_64 and RISC-V.
  • Add debug assertions for invalid transitions, underflow, and ordinary RCU use while RCU is not watching.
  • Define the required LoongArch64 integration points for when that architecture's entry and idle paths become functional.

2. Make CPU hotplug RCU-safe

  • Integrate RCU online/offline transitions with the CPU-hotplug coordinator.
  • Fix the race that can re-add a stopping CPU to a newly started grace period.
  • Add explicit CPU starting, online, dying, and dead responsibilities.
  • Ensure per-CPU RCU state is initialized before an online CPU becomes visible to new grace periods.
  • Define how pending callbacks and grace-period responsibility move away from a dying CPU.
  • Test grace-period creation at every CPU online/offline transition point.
  • Ensure rcu_barrier() and callback draining remain correct during CPU hotplug.

3. Provide an allocation-free core callback path

  • Make RcuHead an intrusive callback node containing the state needed for allocation-free enqueue.
  • Ensure the base call_rcu() path can run in allowed atomic/IRQ contexts without allocating.
  • Remove allocator growth from IRQ-disabled global critical sections.
  • Introduce per-CPU callback queues.
  • Segment callbacks by grace-period state (for example, done/wait/next-ready/next).
  • Keep closure-based rcu_defer() as an explicitly allocating convenience API with clear context restrictions.
  • Provide allocation-free deferred destruction for objects that embed an RCU callback head.
  • Preserve duplicate-enqueue detection and exactly-once callback execution.
  • Revalidate rcu_barrier() semantics after callbacks become per-CPU.

4. Guarantee forward progress and provide observability

  • Record grace-period start time, last progress time, sequence, and holdout CPUs.
  • Add a grace-period progress worker with bounded and documented responsibilities.
  • Request quiescent-state checks from holdout CPUs after a soft timeout.
  • Escalate to reschedule/IPI requests when a CPU does not cooperate.
  • Add an RCU stall detector that reports holdout CPU/task, context state, IRQ/NMI nesting, and callback queue lengths.
  • Add callback batch/time budgets so callback floods or slow callbacks do not monopolize the worker.
  • Export useful debugfs statistics: GP latency, callback queue depth, callbacks invoked, forced-QS attempts, and stalls.
  • Keep the normal fast path quiet when no grace period needs assistance.

5. Build a production-grade validation suite

  • Add deterministic tests for the grace-period and context-tracking state machines.
  • Add memory-ordering/model tests equivalent to the Linux RCU+sync+read and RCU+sync+free patterns.
  • Test continuous hand-over-hand readers; finite readers must not starve a grace period.
  • Test persistent user-mode and idle extended quiescent states.
  • Test nested IRQ/NMI transitions over idle and user contexts.
  • Add randomized SMP reader/writer/callback torture tests.
  • Add callback-flood, slow-callback, and callback-requeue tests.
  • Add CPU online/offline race tests.
  • Add allocator-failure injection around allocating convenience APIs.
  • Test concurrent synchronize_rcu(), call_rcu(), and rcu_barrier().
  • Run the relevant dunitests in a DragonOS QEMU guest on x86_64.
  • Run the relevant dunitests in a DragonOS QEMU guest on RISC-V (currently cross-build/link validated only).
  • Add measurements for GP latency, callback throughput, maximum callback queue depth, and publication CAS retries.
  • Add dedicated scale measurements for IRQ-path overhead and lock contention.

Follow-up milestones

These are tracked here for architectural continuity, but they should start only after the near-term ordinary-RCU foundation is complete.

Scalable ordinary RCU and API completion

  • Replace global hot-path contention with per-CPU state and batched reporting.
  • Evaluate a flat bitmap versus a two-level aggregation tree with measurements up to DragonOS's supported CPU limit.
  • Add asynchronous GP state/cookie polling APIs.
  • Add an expedited grace-period API for proven low-latency teardown requirements.
  • Add typed access/replace/protected-dereference helpers.
  • Add RCU-aware intrusive list/hash traversal helpers where real consumers need them.
  • Provide BH-disabled and preempt-disabled read-side guards without creating separate historical RCU-bh or RCU-sched grace-period engines.

SRCU

  • Define a per-subsystem SRCU domain type.
  • Implement sleepable, nestable read-side guards with cookies.
  • Implement synchronize_srcu(), call_srcu(), srcu_barrier(), and safe domain cleanup.
  • Detect waits on the same SRCU domain from within its read-side critical section.
  • Add sleeping-reader, independent-domain, callback, cleanup, and flood tests.
  • Migrate the first real consumer, such as a blocking notifier or teardown path that genuinely needs sleepable readers.

Preemptible and task-based RCU

  • Design blocked-reader tracking before allowing ordinary RCU readers to be preempted.
  • Cover reader preemption, migration, task exit, and CPU offline.
  • Evaluate priority boosting only if real-time/preemptible RCU requires it.
  • Identify a concrete tracing, BPF, live-patching, or trampoline consumer for Tasks RCU.
  • Implement Tasks RCU holdout scanning only with that consumer and its lifetime rules.
  • Add Tasks Trace RCU only if explicit tracing readers cannot be covered safely by ordinary RCU or SRCU.
  • Keep Tasks Rude RCU deferred unless a consumer requires synchronization with non-watching/preempt-disabled regions.

Acceptance criteria for the first milestone

  • The ordinary RCU contract and memory-ordering invariants are documented.
  • Context tracking is complete and paired on supported x86_64 and RISC-V paths.
  • The identified CPU-offline/new-GP race is fixed and regression-tested.
  • The base intrusive call_rcu() admission path does not allocate.
  • No callback queue growth occurs while holding an IRQ-disabled global lock.
  • A stuck grace period produces an actionable holdout report and has a bounded escalation path.
  • SMP torture, callback flood, hotplug, user/idle/IRQ, and memory-ordering tests pass.
  • Existing RCU users and the rcu_selftest dunitest continue to pass in a DragonOS QEMU guest.

Non-goals

This tracking issue does not require an immediate line-for-line port of Linux Tree RCU. In particular, the following should remain deferred until measurements or consumers justify them:

  • a full multi-level Linux-style rcu_node hierarchy;
  • Tiny RCU as a separate implementation;
  • nocb callback offload and de-offload;
  • lazy callbacks and hurry policies;
  • RCU priority boosting before preemptible/RT RCU exists;
  • VFS RCU path walking;
  • implementing every Linux RCU helper before DragonOS has a consumer.

Linux 6.6 references

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    testUnitest/User space test

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions