We currently union the UNMASKABLE_SIGNALS set with the new signal mask.
This does the complete opposite of what we wnat, we want to *remove*
those signals from the newly computed signal mask.
This patch removes the UNMASKABLE_SIGNALS set from any newly computed
signal mask.
Make it such that when a ptrace event is hit:
- The current regset is saved in the ptrace state.
- The current task is put to sleep.
- Arrange for a SIGCHLD to be set to the parent.
- Notify any waiters with the appopriate signal.
This commit refactors the signal handling subsystem to address a bug in
process creation and to improve the separation of concerns between
signal delivery and signal disposition.
1. Fix Action Table Sharing:
Previously, the signal action table was wrapped in an `Arc`, causing
forked child processes to inadvertently share signal dispositions with
the parent. `SignalActionState` now contains a direct `SigActionSet` and
implements Clone, ensuring that processes receive a private copy of the
action table upon fork/clone.
2. Decouple Signal Selection from Execution:
The logic for selecting a pending signal has been moved from the
disposition state into a new `take_signal` method on `OwnedTask`. This
decouples the "taking" of a signal (respecting masks and priorities)
from the "actioning" of that signal. This is a prerequisite for
implementing ptrace.
3. Various cleanup bits:
- Renamed `SignalState` to `SignalActionState` to more accurately
reflect that it manages signal dispositions.
- Removed the `pending` signal set out of the action state and directly
into the `ThreadGroup` and `OwnedTask`.
- Renamed `set_pending` to `set_signal` for consistency.
- Simplified the signal delivery loop in `dispatch_userspace_task`
using the new `take_signal` API.
Add a new option `--init-arg` which allows arguments to be passed to
init when invoked by the kernel. This allows the `-i` parameter to be
passed through to bash such that it will be started in interactive mode.
Add the proper inode and fs id to the `FileAttr` struct returned by
`getattr`. This prevents the dynamic loader from skipping files which it
considers to be hard-links (share the same inode ID).
Implement FUTEX_{WAKE,WAIT}_BITSET by using a `u32` as a data
discriminant value.
Also add a bunch of tests to `usertest` to ensure proper functionality.
Currently, when a kernel stack overflow occures, the exception handler
blindly attempts to write the current context to the stack. If the SP
isn't valid this causes another fault, and so on - locking up the
system.
This commit re-arranges the stack layout, performs SP validation before
usage and switches to an emergency stack when SP isn't valid. This
allows the handler to run and panic gracefully.
Fixes: #98
Currently, each task implements it's own priority value. In Linux, each
thread group (process) has a default process which all tasks in that
group inherit. Tasks can, however, override the default process
priority.
Implement that logic here which also fixes the current compilation error
on master.
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 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.