Commit 0a7df9f8 authored by Stefan Lankes's avatar Stefan Lankes Committed by Stefan Lankes
Browse files

set task switch flag only if the FPU ownership is able to switch

- reduce the number of interrupts
parent 06917b16
...@@ -60,7 +60,7 @@ pub use crate::arch::x86_64::kernel::processor; ...@@ -60,7 +60,7 @@ pub use crate::arch::x86_64::kernel::processor;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use crate::arch::x86_64::kernel::scheduler; pub use crate::arch::x86_64::kernel::scheduler;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use crate::arch::x86_64::kernel::switch::switch; pub use crate::arch::x86_64::kernel::switch::{switch_to_fpu_owner, switch_to_task};
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use crate::arch::x86_64::kernel::systemtime::get_boot_time; pub use crate::arch::x86_64::kernel::systemtime::get_boot_time;
#[cfg(not(test))] #[cfg(not(test))]
......
...@@ -7,9 +7,10 @@ ...@@ -7,9 +7,10 @@
use crate::arch::x86_64::kernel::gdt::set_current_kernel_stack; use crate::arch::x86_64::kernel::gdt::set_current_kernel_stack;
/// The function triggers a context switch to a new task.
#[inline(never)] #[inline(never)]
#[naked] #[naked]
pub extern "C" fn switch(_old_stack: *mut usize, _new_stack: usize) { pub fn switch_to_task(_old_stack: *mut usize, _new_stack: usize) {
// rdi = old_stack => the address to store the old rsp // rdi = old_stack => the address to store the old rsp
// rsi = new_stack => stack pointer of the new task // rsi = new_stack => stack pointer of the new task
...@@ -68,3 +69,64 @@ pub extern "C" fn switch(_old_stack: *mut usize, _new_stack: usize) { ...@@ -68,3 +69,64 @@ pub extern "C" fn switch(_old_stack: *mut usize, _new_stack: usize) {
); );
} }
} }
/// The function triggers a context switch to an idle task or
/// a task, which is alread owner of the FPU.
/// Consequently the kernel don't set the task switched flag.
#[inline(never)]
#[naked]
pub fn switch_to_fpu_owner(_old_stack: *mut usize, _new_stack: usize) {
// rdi = old_stack => the address to store the old rsp
// rsi = new_stack => stack pointer of the new task
unsafe {
// store context
llvm_asm!(
"pushfq\n\t\
push %rax\n\t\
push %rcx\n\t\
push %rdx\n\t\
push %rbx\n\t\
push %rbp\n\t\
push %rsi\n\t\
push %rdi\n\t\
push %r8\n\t\
push %r9\n\t\
push %r10\n\t\
push %r11\n\t\
push %r12\n\t\
push %r13\n\t\
push %r14\n\t\
push %r15\n\t\
rdfsbaseq %rax\n\t\
push %rax\n\t\
// store the old stack pointer in the dereferenced first parameter\n\t\
// and load the new stack pointer in the second parameter.\n\t\
mov %rsp, (%rdi)\n\t\
mov %rsi, %rsp" :::: "volatile"
);
// set stack pointer in TSS \n\t\
set_current_kernel_stack();
// restore context
llvm_asm!(
"pop %rax\n\t\
wrfsbaseq %rax\n\t\
pop %r15\n\t\
pop %r14\n\t\
pop %r13\n\t\
pop %r12\n\t\
pop %r11\n\t\
pop %r10\n\t\
pop %r9\n\t\
pop %r8\n\t\
pop %rdi\n\t\
pop %rsi\n\t\
pop %rbp\n\t\
pop %rbx\n\t\
pop %rdx\n\t\
pop %rcx\n\t\
pop %rax\n\t\
popfq" :::: "volatile"
);
}
}
...@@ -15,7 +15,7 @@ use core::sync::atomic::{AtomicU32, Ordering}; ...@@ -15,7 +15,7 @@ use core::sync::atomic::{AtomicU32, Ordering};
use crate::arch; use crate::arch;
use crate::arch::irq; use crate::arch::irq;
use crate::arch::percore::*; use crate::arch::percore::*;
use crate::arch::switch; use crate::arch::{switch_to_fpu_owner, switch_to_task};
use crate::collections::AvoidInterrupts; use crate::collections::AvoidInterrupts;
use crate::config::*; use crate::config::*;
use crate::scheduler::task::*; use crate::scheduler::task::*;
...@@ -443,14 +443,18 @@ impl PerCoreScheduler { ...@@ -443,14 +443,18 @@ impl PerCoreScheduler {
} }
// Handle the new task and get information about it. // Handle the new task and get information about it.
let (new_id, new_stack_pointer) = { let (new_id, new_stack_pointer, is_idle) = {
let mut borrowed = task.borrow_mut(); let mut borrowed = task.borrow_mut();
if borrowed.status != TaskStatus::TaskIdle { if borrowed.status != TaskStatus::TaskIdle {
// Mark the new task as running. // Mark the new task as running.
borrowed.status = TaskStatus::TaskRunning; borrowed.status = TaskStatus::TaskRunning;
} }
(borrowed.id, borrowed.last_stack_pointer) (
borrowed.id,
borrowed.last_stack_pointer,
borrowed.status == TaskStatus::TaskIdle,
)
}; };
if id != new_id { if id != new_id {
...@@ -465,7 +469,11 @@ impl PerCoreScheduler { ...@@ -465,7 +469,11 @@ impl PerCoreScheduler {
self.current_task = task; self.current_task = task;
// Finally save our current context and restore the context of the new task. // Finally save our current context and restore the context of the new task.
switch(last_stack_pointer, new_stack_pointer); if is_idle || Rc::ptr_eq(&self.current_task, &self.fpu_owner) {
switch_to_fpu_owner(last_stack_pointer, new_stack_pointer)
} else {
switch_to_task(last_stack_pointer, new_stack_pointer);
}
} }
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment