Add support for closures

This commit is contained in:
Philipp Oppermann
2020-01-23 08:24:25 +01:00
parent b75406b37e
commit 241c1ab2c9
3 changed files with 69 additions and 2 deletions

View File

@@ -8,6 +8,9 @@
#![feature(const_in_array_repeat_expressions)] #![feature(const_in_array_repeat_expressions)]
#![feature(global_asm)] #![feature(global_asm)]
#![feature(asm)] #![feature(asm)]
#![feature(raw)]
#![feature(never_type)]
#![feature(naked_functions)]
#![test_runner(crate::test_runner)] #![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"] #![reexport_test_harness_main = "test_main"]

View File

@@ -54,11 +54,20 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
#[cfg(test)] #[cfg(test)]
test_main(); 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_1, 1, &mut mapper, &mut frame_allocator);
create_thread(thread_2, 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(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!"); println!("It did not crash!");
blog_os::hlt_loop(); blog_os::hlt_loop();

View File

@@ -50,5 +50,60 @@ pub fn create_thread(
let ptr: *mut u64 = stack.as_mut_ptr(); let ptr: *mut u64 = stack.as_mut_ptr();
let rflags = 0x200; let rflags = 0x200;
unsafe { ptr.write(rflags) }; unsafe { ptr.write(rflags) };
unsafe { add_thread(stack) }; add_thread(stack);
}
pub fn create_thread_from_closure<F>(
f: F,
stack_size: u64,
mapper: &mut impl Mapper<Size4KiB>,
frame_allocator: &mut impl FrameAllocator<Size4KiB>,
) 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::<u64>();
let ptr: *mut u64 = stack.as_mut_ptr();
unsafe { ptr.write(call_closure_entry as u64) };
stack -= core::mem::size_of::<u64>();
let ptr: *mut u64 = stack.as_mut_ptr();
let rflags = 0x200;
unsafe { ptr.write(rflags) };
add_thread(stack);
}
type ThreadClosure = alloc::boxed::Box<dyn FnOnce() -> !>;
#[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!();
} }