mirror of
https://github.com/phil-opp/blog_os.git
synced 2025-12-16 14:27:49 +00:00
Add support for closures
This commit is contained in:
@@ -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"]
|
||||
|
||||
|
||||
11
src/main.rs
11
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();
|
||||
|
||||
@@ -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: 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!();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user