Skip to content

Conversation

@hexagonal-sun
Copy link
Owner

@hexagonal-sun hexagonal-sun commented Dec 30, 2025

This commit refactors the core process representation to decouple
"Identity/Resources" from "Execution/Scheduling". Previously, a
monolithic `Task` struct wrapped in `Arc<SpinLock<>>` caused lock
contention during hot scheduling paths and conflated shared state with
CPU-local state.

The `Task` struct has been split into:

1. `Task` (Shared): Holds process-wide resources (VM, FileTable,
Credentials). Managed via `Arc` and internal fine-grained locking.

2. `OwnedTask` (Private): Holds execution state (Context, v_runtime,
signal mask). Strictly owned by a specific CPU (via the Scheduler) and
accessed lock-free.

Key changes:

* Scheduler:
  chedState` now owns tasks via `Box<OwnedTask>`.
  - Transitions between `run_queue` and `running_task` involve strictly
    moving ownership of the Box, ensuring pointer stability.
  - The EEVDF comparison logic now explicitly handles comparisons
    between the queued candidates and the currently running task (which is
    not in the queue).

* Current Task Access:
  - `current()` now returns a `CurrentTaskGuard` which:
    1. Disables preemption (preventing context switches while holding
       the reference).
    2. Performs a runtime borrow check (panic on double-mutable borrow).
    3. Dereferences a cached Per-CPU raw pointer for O(1) access.

Also includes:

sched: implement fast-path return

Previously, the scheduler unconditionally performed a full runqueue
search:(`find_next_runnable_desc`) on every invocation, including every
timer tick and syscall return. This resulted in unnecessary overhead.

This change introduces a "lazy preemption" model:

1. Fast-Path Optimization: `do_schedule` now checks if the current task
   is valid, is not the Idle task, and still has virtual budget remaining.
   If these conditions are met and `force_resched` is not set, the
   scheduler returns immediately without locking the runqueue.

2. Preemption & Idle Handling:
   - `insert_into_runq` now sets `force_resched` if the new task has an
     earlier deadline than the current task, or if the current task is
     Idle.
   - The Idle task is explicitly excluded from the fast-path to ensure
     immediate context switching when new work arrives.

This is now at a point where it's ready for review. @some100 this also touches some of the FS changes you've been making recently, might be worth having a quick look. Thanks!

Fixes: #94

@hexagonal-sun hexagonal-sun force-pushed the implement-ownedtask branch 3 times, most recently from 4fa9905 to ecaa9be Compare January 1, 2026 21:10
hexagonal-sun and others added 3 commits January 1, 2026 22:54
This commit refactors the core process representation to decouple
"Identity/Resources" from "Execution/Scheduling". Previously, a
monolithic `Task` struct wrapped in `Arc<SpinLock<>>` caused lock
contention during hot scheduling paths and conflated shared state with
CPU-local state.

The `Task` struct has been split into:

1. `Task` (Shared): Holds process-wide resources (VM, FileTable,
Credentials). Managed via `Arc` and internal fine-grained locking.

2. `OwnedTask` (Private): Holds execution state (Context, v_runtime,
signal mask). Strictly owned by a specific CPU (via the Scheduler) and
accessed lock-free.

Key changes:

* Scheduler:
  chedState` now owns tasks via `Box<OwnedTask>`.
  - Transitions between `run_queue` and `running_task` involve strictly
    moving ownership of the Box, ensuring pointer stability.
  - The EEVDF comparison logic now explicitly handles comparisons
    between the queued candidates and the currently running task (which is
    not in the queue).

* Current Task Access:
  - `current()` now returns a `CurrentTaskGuard` which:
    1. Disables preemption (preventing context switches while holding
       the reference).
    2. Performs a runtime borrow check (panic on double-mutable borrow).
    3. Dereferences a cached Per-CPU raw pointer for O(1) access.
Previously, the scheduler unconditionally performed a full runqueue
search:(`find_next_runnable_desc`) on every invocation, including every
timer tick and syscall return. This resulted in unnecessary overhead.

This change introduces a "lazy preemption" model:

1. Fast-Path Optimization: `do_schedule` now checks if the current task
   is valid, is not the Idle task, and still has virtual budget remaining.
   If these conditions are met and `force_resched` is not set, the
   scheduler returns immediately without locking the runqueue.

2. Preemption & Idle Handling:
   - `insert_into_runq` now sets `force_resched` if the new task has an
     earlier deadline than the current task, or if the current task is
     Idle.
   - The Idle task is explicitly excluded from the fast-path to ensure
     immediate context switching when new work arrives.
@hexagonal-sun hexagonal-sun marked this pull request as ready for review January 1, 2026 22:55
Add various fixes to get an SMP version of `usertest` working with SMP.
use log::info;

const KERNEL_STACK_SZ: usize = 64 * 1024; // 32 KiB
const KERNEL_STACK_SZ: usize = 256 * 1024; // 32 KiB
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Outdated comment

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider a OwnedTask struct

4 participants