diff --git a/src/main.rs b/src/main.rs index 9674abf5..ba18c561 100644 --- a/src/main.rs +++ b/src/main.rs @@ -74,6 +74,7 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { fn idle_thread() -> ! { loop { x86_64::instructions::hlt(); + multitasking::yield_now(); } } diff --git a/src/multitasking/mod.rs b/src/multitasking/mod.rs index 082f23ef..3f48f61f 100644 --- a/src/multitasking/mod.rs +++ b/src/multitasking/mod.rs @@ -9,6 +9,7 @@ static SCHEDULER: spin::Mutex> = spin::Mutex::new(None); #[repr(u64)] pub enum SwitchReason { Paused, + Yield, Blocked, Exit, } @@ -29,19 +30,22 @@ pub fn invoke_scheduler() { } pub fn exit_thread() -> ! { + synchronous_context_switch(SwitchReason::Exit).expect("can't exit last thread"); + unreachable!("finished thread continued"); +} + +pub fn yield_now() { + let _ = synchronous_context_switch(SwitchReason::Yield); +} + +fn synchronous_context_switch(reason: SwitchReason) -> Result<(), ()> { let next = with_scheduler(|s| s.schedule()); match next { - Some((next_stack_pointer, prev_thread_id)) => { - unsafe { - context_switch::context_switch_to( - next_stack_pointer, - prev_thread_id, - SwitchReason::Exit, - ) - } - unreachable!("finished thread continued") - } - None => panic!("can't exit last thread"), + Some((next_stack_pointer, prev_thread_id)) => unsafe { + context_switch::context_switch_to(next_stack_pointer, prev_thread_id, reason); + Ok(()) + }, + None => Err(()), } } diff --git a/src/multitasking/scheduler.rs b/src/multitasking/scheduler.rs index e09a709f..328c56a8 100644 --- a/src/multitasking/scheduler.rs +++ b/src/multitasking/scheduler.rs @@ -74,7 +74,9 @@ impl Scheduler { return; // do nothing } match switch_reason { - SwitchReason::Paused => self.paused_threads.push_back(paused_thread_id), + SwitchReason::Paused | SwitchReason::Yield => { + self.paused_threads.push_back(paused_thread_id) + } SwitchReason::Blocked => { self.blocked_threads.insert(paused_thread_id); self.check_for_wakeup(paused_thread_id);