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

ThreadBuilder

Struct ThreadBuilder 

Source
pub struct ThreadBuilder { /* private fields */ }
Expand description

Builder for creating new threads with specific configurations.

ThreadBuilder follows the builder pattern to construct a Thread with custom stack sizes, priority, CPU affinity, TLS base, and filesystem state. The build method allocates physical frames for both user and kernel stacks, assigns virtual address regions with guard pages, and initializes the thread’s CPU context.

§Example

let thread = ThreadBuilder::new(pid, "worker".into(), entry_fn as usize)
    .user_stack_size(2 * 1024 * 1024)  // 2 MB user stack
    .priority(3)
    .cpu_affinity(0x3)                  // CPUs 0 and 1
    .build()?;

§Defaults

  • User stack: 1 MB
  • Kernel stack: 64 KB
  • Priority: 2 (normal)
  • CPU affinity: all CPUs (usize::MAX)
  • TLS base: None (no TLS)
  • Filesystem state: new root (“/”, umask 0o022)

Implementations§

Source§

impl ThreadBuilder

Source

pub fn new(process: ProcessId, name: String, entry_point: usize) -> Self

Create a new thread builder with required parameters.

§Arguments
  • process: The parent process ID that owns this thread.
  • name: Human-readable thread name (for debugging/logging).
  • entry_point: Virtual address where thread execution begins.
Source

pub fn user_stack_size(self, size: usize) -> Self

Set user stack size

Source

pub fn kernel_stack_size(self, size: usize) -> Self

Set kernel stack size

Source

pub fn priority(self, priority: u8) -> Self

Set priority

Source

pub fn cpu_affinity(self, mask: usize) -> Self

Set CPU affinity

Source

pub fn clear_tid(self, ptr: usize) -> Self

Set clear_tid pointer for CLONE_CHILD_CLEARTID

Source

pub fn fs(self, fs: Arc<ThreadFs>) -> Self

Set the filesystem view (cwd/umask) for the new thread.

When creating a thread via clone() with CLONE_FS, pass a shared Arc<ThreadFs> from the parent. Without CLONE_FS, pass a copy via ThreadFs::clone_copy. If not set, the builder defaults to a new root filesystem state.

Source

pub fn tls_base(self, base: usize) -> Self

Set the TLS (Thread-Local Storage) base address for the new thread.

This corresponds to CLONE_SETTLS on Linux or arch_prctl(ARCH_SET_FS) on x86_64. The base address is written into the architecture-specific TLS register (FS base on x86_64, TPIDR_EL0 on AArch64, tp on RISC-V) when the thread is first scheduled.

Source

pub fn build(self) -> Result<Thread, KernelError>

Build the thread with real stack allocation.

Allocates physical frames for the kernel stack via the global frame allocator. User stack frames are NOT allocated here because every caller immediately maps user stack pages through the VAS (via map_page()), which allocates its own tracked frames. Allocating frames here would orphan them (never freed, never used), leaking 64 pages (256 KB) per thread – the root cause of the native-compilation OOM.

Kernel stack frames are stored in Stack::phys_frame so that cleanup_process() can free them without walking page tables.

Each stack gets a guard page (unmapped) below it to detect overflow. Stack pointers are set to the top of each allocated region since stacks grow downward on all supported architectures (x86_64, AArch64, RISC-V).

Auto Trait Implementations§

§

impl Freeze for ThreadBuilder

§

impl !RefUnwindSafe for ThreadBuilder

§

impl Send for ThreadBuilder

§

impl Sync for ThreadBuilder

§

impl Unpin for ThreadBuilder

§

impl !UnwindSafe for ThreadBuilder

Blanket Implementations§

§

impl<T> Any for T
where T: 'static + ?Sized,

§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<T> Borrow<T> for T
where T: ?Sized,

§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
§

impl<T> BorrowMut<T> for T
where T: ?Sized,

§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> From<T> for T

§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T, U> Into<U> for T
where U: From<T>,

§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of [From]<T> for U chooses to do.

§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.