⚠️ VeridianOS Kernel Documentation - This is low-level kernel code. All functions are unsafe unless explicitly marked otherwise. no_std

veridian_kernel/process/
lifecycle.rs

1//! Process lifecycle management
2//!
3//! This module handles process creation, termination, and state transitions.
4//! The implementation is split into focused submodules:
5//! - [`creation`](super::creation): Process creation, exec, and stack setup
6//! - [`fork`](super::fork): Process forking with address space cloning
7//! - [`exit`](super::exit): Process exit, cleanup, signals, wait, and
8//!   statistics
9
10// Re-export everything from submodules to maintain existing API
11// Re-export wait_process (used by parent module re-exports)
12#[cfg(feature = "alloc")]
13pub use super::exit::wait_process;
14pub use super::{
15    creation::{
16        create_process, create_process_with_options, exec_process, parse_shebang, search_path,
17        ProcessCreateOptions, DEFAULT_KERNEL_STACK_SIZE, DEFAULT_USER_STACK_SIZE,
18    },
19    exit::{
20        cleanup_thread, default_signal_action, exit_process, get_process_stats, kill_process,
21        reap_zombie_threads, signals, ProcessStats, SignalAction, WaitOptions,
22    },
23    fork::fork_process,
24};
25use super::{pcb::Process, thread::Thread, ProcessPriority};
26#[allow(unused_imports)]
27use crate::{arch::context::ThreadContext, error::KernelError, println, sched};
28
29/// Create scheduler task for thread
30///
31/// This is a shared helper used by both process creation and forking.
32/// It bridges the process/thread model with the scheduler's task model.
33///
34/// The Task is heap-allocated (Box) for two reasons:
35/// 1. Avoids stack overflow on architectures with large context structs (e.g.,
36///    RISC-V/AArch64 FPU state) during deep boot call chains.
37/// 2. The scheduler stores a raw pointer to the Task, so it must outlive this
38///    function — Box::into_raw provides stable heap ownership.
39pub(super) fn create_scheduler_task(process: &Process, thread: &Thread) -> Result<(), KernelError> {
40    // Get thread context info
41    let ctx = thread.context.lock();
42    let instruction_pointer = ctx.get_instruction_pointer();
43    let stack_pointer = ctx.get_stack_pointer();
44    drop(ctx);
45
46    // Heap-allocate the Task to avoid stack overflow and provide a stable
47    // pointer for the scheduler (which outlives this function).
48    #[cfg(feature = "alloc")]
49    {
50        let name = process.name.clone();
51        let page_table = process.memory_space.lock().get_page_table() as usize;
52
53        let mut task = alloc::boxed::Box::new(sched::task::Task::new(
54            process.pid,
55            thread.tid,
56            name,
57            instruction_pointer,
58            stack_pointer,
59            page_table,
60        ));
61
62        // Update task fields based on thread/process state
63        task.priority = match *process.priority.lock() {
64            ProcessPriority::RealTime => sched::task::Priority::RealTimeHigh,
65            ProcessPriority::System => sched::task::Priority::SystemHigh,
66            ProcessPriority::Normal => sched::task::Priority::UserNormal,
67            ProcessPriority::Low => sched::task::Priority::UserLow,
68            ProcessPriority::Idle => sched::task::Priority::Idle,
69        };
70
71        task.sched_class = match *process.priority.lock() {
72            ProcessPriority::RealTime => sched::task::SchedClass::RealTime,
73            _ => sched::task::SchedClass::Normal,
74        };
75
76        task.time_slice = thread
77            .time_slice
78            .load(core::sync::atomic::Ordering::Acquire);
79
80        // Transfer ownership to raw pointer — scheduler takes ownership
81        let task_ptr = core::ptr::NonNull::new(alloc::boxed::Box::into_raw(task)).ok_or(
82            KernelError::ResourceExhausted {
83                resource: "task pointer allocation",
84            },
85        )?;
86
87        // Add to scheduler
88        let scheduler = sched::SCHEDULER.lock();
89        scheduler.enqueue(task_ptr);
90    }
91
92    Ok(())
93}