diff --git a/src/lib.rs b/src/lib.rs index 170bd639..8670e75e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,9 @@ #![feature(const_in_array_repeat_expressions)] #![feature(global_asm)] #![feature(asm)] +#![feature(raw)] +#![feature(never_type)] +#![feature(naked_functions)] #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] diff --git a/src/main.rs b/src/main.rs index b221ac2f..5da8d70f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,11 +54,20 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { #[cfg(test)] test_main(); - use blog_os::multitasking::create_thread; + use blog_os::multitasking::{create_thread, create_thread_from_closure}; create_thread(thread_1, 1, &mut mapper, &mut frame_allocator); create_thread(thread_2, 1, &mut mapper, &mut frame_allocator); create_thread(thread_3, 1, &mut mapper, &mut frame_allocator); + create_thread_from_closure( + || loop { + print!("4"); + x86_64::instructions::hlt(); + }, + 1, + &mut mapper, + &mut frame_allocator, + ); println!("It did not crash!"); blog_os::hlt_loop(); diff --git a/src/multitasking.rs b/src/multitasking.rs index fa36910b..ef2a4454 100644 --- a/src/multitasking.rs +++ b/src/multitasking.rs @@ -50,5 +50,60 @@ pub fn create_thread( let ptr: *mut u64 = stack.as_mut_ptr(); let rflags = 0x200; unsafe { ptr.write(rflags) }; - unsafe { add_thread(stack) }; + add_thread(stack); +} + +pub fn create_thread_from_closure( + f: F, + stack_size: u64, + mapper: &mut impl Mapper, + frame_allocator: &mut impl FrameAllocator, +) where + F: FnOnce() -> ! + 'static, +{ + use alloc::boxed::Box; + use core::{mem, raw::TraitObject}; + + let boxed: ThreadClosure = Box::new(f); + let trait_object: TraitObject = unsafe { mem::transmute(boxed) }; + + let mut stack = crate::memory::alloc_stack(stack_size, mapper, frame_allocator).unwrap(); + + // push trait object + stack -= core::mem::size_of::<*mut ()>(); + let ptr: *mut *mut () = stack.as_mut_ptr(); + unsafe { ptr.write(trait_object.data) }; + stack -= core::mem::size_of::<*mut ()>(); + let ptr: *mut *mut () = stack.as_mut_ptr(); + unsafe { ptr.write(trait_object.vtable) }; + + stack -= core::mem::size_of::(); + let ptr: *mut u64 = stack.as_mut_ptr(); + unsafe { ptr.write(call_closure_entry as u64) }; + stack -= core::mem::size_of::(); + let ptr: *mut u64 = stack.as_mut_ptr(); + let rflags = 0x200; + unsafe { ptr.write(rflags) }; + add_thread(stack); +} + +type ThreadClosure = alloc::boxed::Box !>; + +#[no_mangle] +unsafe fn call_closure(data: *mut (), vtable: *mut ()) -> ! { + use core::{mem, raw::TraitObject}; + + let trait_object = TraitObject { data, vtable }; + let f: ThreadClosure = mem::transmute(trait_object); + f() +} + +#[naked] +unsafe fn call_closure_entry() -> ! { + asm!(" + pop rsi + pop rdi + call call_closure + " ::: "mem" : "intel", "volatile"); + unreachable!(); }