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(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"]
|
||||||
|
|
||||||
|
|||||||
11
src/main.rs
11
src/main.rs
@@ -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();
|
||||||
|
|||||||
@@ -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!();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user