diff --git a/Cargo.toml b/Cargo.toml index ae67fe5a..abd3c540 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,3 +33,6 @@ test-args = [ "-display", "none" ] test-success-exit-code = 33 # (0x10 << 1) | 1 + +[profile.release] +lto = true \ No newline at end of file diff --git a/src/multitasking.rs b/src/multitasking.rs new file mode 100644 index 00000000..fa36910b --- /dev/null +++ b/src/multitasking.rs @@ -0,0 +1,54 @@ +use alloc::collections::VecDeque; +use lazy_static::lazy_static; +use x86_64::structures::paging::{FrameAllocator, Mapper, Size4KiB}; +use x86_64::VirtAddr; + +global_asm!(include_str!("multitasking/context_switch.s")); + +pub unsafe fn context_switch(stack_pointer: VirtAddr) { + asm!( + "call asm_context_switch" + : + : "{rdi}"(stack_pointer.as_u64()) + : "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rpb", "r8", "r9", "r10", + "r11", "r12", "r13", "r14", "r15", "rflags", "memory" + : "intel", "volatile" + ); +} + +pub fn scheduler() { + let next = PAUSED_THREADS.try_lock().and_then(|mut t| t.pop_front()); + if let Some(next) = next { + unsafe { context_switch(next) }; + } +} + +lazy_static! { + static ref PAUSED_THREADS: spin::Mutex> = spin::Mutex::new(VecDeque::new()); +} + +#[no_mangle] +fn add_paused_thread(stack_pointer: VirtAddr) { + add_thread(stack_pointer) +} + +fn add_thread(stack_pointer: VirtAddr) { + PAUSED_THREADS.lock().push_back(stack_pointer); +} + +pub fn create_thread( + f: fn() -> !, + stack_size: u64, + mapper: &mut impl Mapper, + frame_allocator: &mut impl FrameAllocator, +) { + let mut stack = crate::memory::alloc_stack(stack_size, mapper, frame_allocator).unwrap(); + stack -= core::mem::size_of::(); + let ptr: *mut u64 = stack.as_mut_ptr(); + unsafe { ptr.write(f as u64) }; + stack -= core::mem::size_of::(); + let ptr: *mut u64 = stack.as_mut_ptr(); + let rflags = 0x200; + unsafe { ptr.write(rflags) }; + unsafe { add_thread(stack) }; +} diff --git a/src/multitasking/context_switch.s b/src/multitasking/context_switch.s new file mode 100644 index 00000000..a4740a9a --- /dev/null +++ b/src/multitasking/context_switch.s @@ -0,0 +1,13 @@ +.intel_syntax noprefix + +asm_context_switch: + pushfq + + mov rax, rsp + mov rsp, rdi + + mov rdi, rax + call add_paused_thread + + popfq + ret