1use crate::arch::x86_64::arch_regs::{Context64, TrapFrame};
2use crate::arch::x86_64::paging::{address_space_clone, get_cr3};
3use crate::arch::x86_64::{arch_regs, is_int_enabled};
4use crate::mm::vmm::{VMArea, VMMan, VMPerms, VMType};
5use crate::mm::KSTACK_ALLOCATOR;
6use crate::proc::exec::child_task_entry;
7use crate::proc::sched::GLOBAL_SCHEDULER;
8use crate::proc::sync::bellringer::{BellRinger, Sleeper};
9use crate::{defs::*, Scheduler};
10use alloc::collections::VecDeque;
11use alloc::string::String;
12use core::ops::Range;
13use core::ptr;
14use core::str::FromStr;
15#[repr(C)]
25pub struct Task {
26 pub magic: u64,
27 pub pid: u64,
28 pub kernel_stack: u64,
30 pub mm: VMMan,
31 pub page_root_va: u64,
32 pub state: TaskState,
36 pub context: arch_regs::Context64,
37}
38
39#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
46pub struct TaskId(u64);
47
48impl TaskId {
49 pub fn new(addr: u64) -> Self { Self(addr) }
50
51 pub fn get_task_ref(&self) -> &Task {
52 return unsafe { &*(self.0 as *mut Task) };
53 }
54
55 pub fn get_task_ref_mut(&self) -> &mut Task {
56 return unsafe { &mut *(self.0 as *mut Task) };
57 }
58}
59
60#[derive(Debug, PartialEq)]
64pub enum TaskState {
65 Run,
66 Wait,
67 Block, Dead, Eating,
70 Purr,
71 Meow,
72 Angry,
73}
74
75extern "C" {
76 pub fn context_swap(from_ctx: u64, to_ctx: u64);
79 pub fn context_swap_to(to_ctx: u64);
80}
81
82impl Task {
85 #[inline(always)]
88 unsafe fn settle_on_stack<'a>(stack_addr: u64, t: Task) -> &'a mut Task {
89 ptr::write_volatile(stack_addr as *mut Task, t);
90 return &mut *(stack_addr as *mut Task);
91 }
92
93 #[inline(always)]
96 fn prepare_context(&mut self, entry: u64) {
97 let mut sp = self.get_init_kernel_sp();
98 unsafe {
99 sp -= 8;
100 *(sp as *mut u64) = 0;
101 sp -= 8;
102 *(sp as *mut u64) = entry;
103 }
104 self.context.rsp = sp;
105 }
106
107 #[inline(always)]
111 pub fn get_init_kernel_sp(&self) -> u64 {
112 let mut sp = self.kernel_stack + Mem::KERNEL_STACK_SIZE;
113 sp &= !0b111;
114 sp
115 }
116
117 pub fn current<'a>() -> Option<&'a mut Task> {
126 let addr = arch_regs::get_sp() & !Mem::KERNEL_STACK_MASK;
127 let t = unsafe { &mut *(addr as *mut Task) };
128 if t.magic != Mem::KERNEL_STACK_TASK_MAGIC {
129 return None;
130 }
131 return Some(t);
132 }
133
134 #[inline]
135 pub fn taskid(&self) -> TaskId { TaskId::new(self as *const _ as u64) }
136
137 pub unsafe fn curr_wait_in(wait_room: &mut VecDeque<TaskId>) {
141 let t = Task::current().unwrap();
142 debug_assert_ne!(t.state, TaskState::Wait);
143 t.state = TaskState::Wait;
144 wait_room.push_back(t.taskid());
145 }
146
147 pub unsafe fn wakeup(&mut self) {
150 if self.state != TaskState::Wait {
151 return;
153 }
154 self.state = TaskState::Run;
156 let sched = GLOBAL_SCHEDULER.get_ref_mut_unguarded();
157 sched.insert_task(self.taskid());
158 }
159
160 pub fn nanosleep(&mut self, ns: u64) {
161 debug_assert!(self.state == TaskState::Run);
162 self.state = TaskState::Wait;
163 BellRinger::check_in(Sleeper::new(self.taskid(), ns));
164 debug_assert!(is_int_enabled());
165 Scheduler::yield_cpu();
166 }
167
168 pub fn create_task(pid: u64, entry: u64) -> TaskId {
171 let sp = unsafe { KSTACK_ALLOCATOR.lock().allocate() };
172 let tid = TaskId::new(sp);
173 println!("new task on {:#X}", sp);
174 let src_root_va = P2V(get_cr3()).unwrap();
175 let root_va = unsafe { address_space_clone(src_root_va).unwrap() };
176 println!("new addr space{:#X}", root_va);
177
178 let nt = unsafe {
179 Task::settle_on_stack(
180 sp,
181 Task {
182 magic: Mem::KERNEL_STACK_TASK_MAGIC,
183 pid,
184 kernel_stack: sp,
185 state: TaskState::Run,
186 context: Context64::default(),
187 mm: VMMan::new(),
188 page_root_va: root_va,
189 },
190 )
191 };
192 nt.mm.vmas.push(VMArea {
194 vm_range: Range::<u64> {
195 start: Mem::ID_MAP_START,
196 end: Mem::ID_MAP_END,
197 },
198 tag: String::from_str("KERNEL IDMAP").unwrap(),
199 user_perms: VMPerms::NONE,
200 backing: VMType::ANOM,
201 });
202 nt.mm.vmas.push(VMArea {
204 vm_range: Range::<u64> {
205 start: Mem::KERNEL_OFFSET,
206 end: Mem::KERNEL_OFFSET + 64 * Mem::G,
207 },
208 tag: String::from_str("KERNEL").unwrap(),
209 user_perms: VMPerms::NONE,
210 backing: VMType::ANOM,
211 });
212 nt.mm.vmas.push(VMArea {
214 vm_range: Range::<u64> {
215 start: Mem::USER_STACK_START,
216 end: Mem::USER_STACK_START + Mem::USER_STACK_SIZE,
217 },
218 tag: String::from_str("USER STACK").unwrap(),
219 user_perms: VMPerms::R | VMPerms::W,
220 backing: VMType::ANOM,
221 });
222 nt.prepare_context(entry);
223 tid
224 }
225
226 pub fn clone_task_user(&self, fp_parent: u64, pid: u64) -> TaskId {
238 let ksp_bottom = unsafe { KSTACK_ALLOCATOR.lock().allocate() };
239 let tid = TaskId::new(ksp_bottom);
240 let src_root_va = P2V(get_cr3()).unwrap();
241 let root_va = unsafe { address_space_clone(src_root_va).unwrap() };
242 let nt = unsafe {
247 Task::settle_on_stack(
248 ksp_bottom,
249 Task {
250 magic: Mem::KERNEL_STACK_TASK_MAGIC,
251 pid,
252 kernel_stack: ksp_bottom,
253 state: TaskState::Run,
254 context: Context64::default(),
255 mm: self.mm.clone(),
256 page_root_va: root_va,
257 },
258 )
259 };
260
261 let mut sp = nt.get_init_kernel_sp();
263 let tf_size = core::mem::size_of::<TrapFrame>();
264 sp -= tf_size as u64;
265
266 unsafe {
267 ptr::copy_nonoverlapping(
268 fp_parent as *const u8,
269 sp as *mut u8,
270 tf_size,
271 )
272 }
273
274 let child_tf = sp as *mut TrapFrame;
275
276 unsafe {
278 (*child_tf).rax = 0;
279 }
280
281 sp -= 8;
282 unsafe {
283 *(sp as *mut u64) = child_task_entry as *const () as u64;
284 }
285 nt.context.rsp = sp;
286 tid
287 }
288}