1use core::num::NonZero;
3use core::ops::Range;
4use core::ptr::NonNull;
5
6use hal::Stack;
7
8use hal::stack::Stacklike;
9
10use crate::mem;
11
12use crate::mem::alloc::{Allocator, BestFitAllocator};
13use crate::sched::thread::{ThreadDescriptor, ThreadId, Timing};
14use crate::utils::KernelError;
15
16#[repr(u16)]
18#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Eq, Ord)]
19pub enum TaskId {
20 User(usize),
22 Kernel(usize),
24}
25
26impl TaskId {
27 pub fn is_user(&self) -> bool {
29 matches!(self, TaskId::User(_))
30 }
31
32 pub fn is_kernel(&self) -> bool {
34 matches!(self, TaskId::Kernel(_))
35 }
36
37 pub fn new_user(id: usize) -> Self {
38 TaskId::User(id)
39 }
40
41 pub fn new_kernel(id: usize) -> Self {
42 TaskId::Kernel(id)
43 }
44}
45
46impl Into<usize> for TaskId {
47 fn into(self) -> usize {
48 match self {
49 TaskId::User(id) => id,
50 TaskId::Kernel(id) => id,
51 }
52 }
53}
54
55pub struct TaskDescriptor {
57 pub mem_size: usize,
59}
60
61pub struct Task {
63 pub id: TaskId,
65 memory: TaskMemory,
67 tid_cntr: usize,
69 threads: mem::array::Vec<ThreadId, 4>,
71}
72
73impl Task {
74 pub fn new(memory_size: usize, id: TaskId) -> Result<Self, KernelError> {
80 let memory = TaskMemory::new(memory_size)?;
81 let threads = mem::array::Vec::new();
82
83 Ok(Self {
84 id,
85 memory,
86 tid_cntr: 0,
87 threads,
88 })
89 }
90
91 fn allocate_tid(&mut self) -> ThreadId {
92 let tid = self.tid_cntr;
93 self.tid_cntr += 1;
94
95 ThreadId::new(tid, self.id)
96 }
97
98 pub fn create_thread(
99 &mut self,
100 entry: extern "C" fn(),
101 fin: Option<extern "C" fn() -> !>,
102 timing: Timing,
103 ) -> Result<ThreadDescriptor, KernelError> {
104 let stack_size = NonZero::new(4096usize).unwrap();
107 let stack_mem = self.memory.malloc(stack_size.into(), align_of::<u128>())?;
109 let stack_top = unsafe { stack_mem.byte_add(stack_size.get()) };
110
111 let stack = hal::stack::StackDescriptor {
112 top: stack_top,
113 size: stack_size,
114 entry,
115 fin,
116 };
117
118 let stack = unsafe { Stack::new(stack) }?;
119
120 let tid = self.allocate_tid();
121
122 self.register_thread(tid)?;
124
125 Ok(ThreadDescriptor { tid, stack, timing })
126 }
127
128 fn register_thread(&mut self, thread_id: ThreadId) -> Result<(), KernelError> {
134 self.threads.push(thread_id)
135 }
136}
137
138pub struct TaskMemory {
140 begin: NonNull<u8>,
142 size: usize,
144
145 alloc: BestFitAllocator,
147}
148
149impl TaskMemory {
150 pub fn new(size: usize) -> Result<Self, KernelError> {
156 let begin = mem::malloc(size, align_of::<u128>()).ok_or(KernelError::OutOfMemory)?;
157
158 let mut alloc = BestFitAllocator::new();
159 let range = Range {
160 start: begin.as_ptr() as usize,
161 end: begin.as_ptr() as usize + size,
162 };
163
164 if let Err(e) = unsafe { alloc.add_range(range) } {
165 unsafe { mem::free(begin, size) };
166 return Err(e);
167 }
168
169 Ok(Self { begin, size, alloc })
170 }
171
172 pub fn malloc<T>(&mut self, size: usize, align: usize) -> Result<NonNull<T>, KernelError> {
173 self.alloc.malloc(size, align)
174 }
175
176 pub fn free<T>(&mut self, ptr: NonNull<T>, size: usize) {
177 unsafe { self.alloc.free(ptr, size) }
178 }
179}
180
181impl Drop for TaskMemory {
182 fn drop(&mut self) {
183 unsafe { mem::free(self.begin, self.size) };
184 }
185}