This commit is contained in:
parent
cce07b9636
commit
4c632e5df2
3 changed files with 48 additions and 20 deletions
|
@ -14,6 +14,11 @@ use crate::{
|
|||
RSDP_ADDRESS,
|
||||
};
|
||||
|
||||
use super::{
|
||||
sync::{lock_kernel, unlock_kernel},
|
||||
task::{CURRENT_TASK, MULTITASKING_ENABLED},
|
||||
};
|
||||
|
||||
pub const AE_OK: ACPI_STATUS = 0;
|
||||
|
||||
#[no_mangle]
|
||||
|
@ -59,8 +64,16 @@ extern "C" fn AcpiOsGetRootPointer() -> ACPI_PHYSICAL_ADDRESS {
|
|||
}
|
||||
#[no_mangle]
|
||||
extern "C" fn AcpiOsGetThreadId() -> UINT64 {
|
||||
// TODO
|
||||
1
|
||||
if !MULTITASKING_ENABLED.load(Ordering::Relaxed) {
|
||||
return 1;
|
||||
}
|
||||
let task_id;
|
||||
lock_kernel();
|
||||
{
|
||||
task_id = CURRENT_TASK.lock().as_ref().unwrap().id;
|
||||
}
|
||||
unlock_kernel();
|
||||
task_id as UINT64
|
||||
}
|
||||
#[no_mangle]
|
||||
extern "C" fn AcpiOsGetTimer() {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use core::arch::asm;
|
||||
use core::{arch::asm, sync::atomic::Ordering};
|
||||
|
||||
use alloc::collections::vec_deque::VecDeque;
|
||||
use spin::Mutex;
|
||||
|
@ -8,13 +8,16 @@ use crate::cpu::isr::ISRState;
|
|||
use super::{
|
||||
lapic::schedule_timer_interrupt,
|
||||
sync::{lock_kernel, unlock_kernel},
|
||||
task::{switch_task, Task, TaskState, CURRENT_TASK},
|
||||
task::{switch_task, Task, TaskState, CURRENT_TASK, MULTITASKING_ENABLED},
|
||||
};
|
||||
|
||||
static SCHEDULER_LIST: Mutex<VecDeque<Task>> = Mutex::new(VecDeque::new());
|
||||
pub static IDLE_TASK: Mutex<Option<Task>> = Mutex::new(None);
|
||||
|
||||
pub fn scheduler(state: &mut ISRState) {
|
||||
if !MULTITASKING_ENABLED.load(Ordering::Relaxed) {
|
||||
return;
|
||||
}
|
||||
lock_kernel();
|
||||
let mut switch_to_task = None;
|
||||
{
|
||||
|
@ -44,11 +47,13 @@ pub fn scheduler(state: &mut ISRState) {
|
|||
}
|
||||
pub fn schedule_task(task: Task) {
|
||||
lock_kernel();
|
||||
let mut scheduler_list = SCHEDULER_LIST.lock();
|
||||
if scheduler_list.is_empty() {
|
||||
schedule_timer_interrupt();
|
||||
{
|
||||
let mut scheduler_list = SCHEDULER_LIST.lock();
|
||||
if scheduler_list.is_empty() {
|
||||
schedule_timer_interrupt();
|
||||
}
|
||||
scheduler_list.push_back(task);
|
||||
}
|
||||
scheduler_list.push_back(task);
|
||||
unlock_kernel();
|
||||
}
|
||||
pub fn yield_task() {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use core::{arch::asm, sync::atomic::AtomicU64};
|
||||
use core::{
|
||||
arch::asm,
|
||||
sync::atomic::{AtomicBool, AtomicU64, AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use alloc::boxed::Box;
|
||||
use kernel_common::instructions::hlt;
|
||||
|
@ -24,6 +27,7 @@ pub enum TaskState {
|
|||
}
|
||||
|
||||
pub struct Task {
|
||||
pub id: usize,
|
||||
state: ISRState,
|
||||
kernel_stack: u64,
|
||||
initial_func: fn(),
|
||||
|
@ -31,6 +35,7 @@ pub struct Task {
|
|||
}
|
||||
|
||||
const STACK_SIZE: usize = 64 * 1024;
|
||||
static NEXT_TASK_ID: AtomicUsize = AtomicUsize::new(2);
|
||||
|
||||
#[repr(align(16))]
|
||||
#[repr(C)]
|
||||
|
@ -38,6 +43,7 @@ struct Stack([u8; STACK_SIZE]);
|
|||
|
||||
pub static CURRENT_TASK: Mutex<Option<Task>> = Mutex::new(None);
|
||||
static RFLAGS: AtomicU64 = AtomicU64::new(0);
|
||||
pub static MULTITASKING_ENABLED: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
pub fn allocate_stack() -> u64 {
|
||||
Box::leak(Box::new(Stack([0; STACK_SIZE]))) as *mut Stack as u64 + STACK_SIZE as u64
|
||||
|
@ -49,23 +55,26 @@ fn destroy_task(task: Task) {
|
|||
}
|
||||
pub fn switch_task(current_state: &mut ISRState, new_task: Task) {
|
||||
lock_kernel();
|
||||
let mut _current_task = CURRENT_TASK.lock();
|
||||
if let Some(current_task) = _current_task.as_mut() {
|
||||
current_task.state = *current_state;
|
||||
match current_task.task_state {
|
||||
TaskState::READY => schedule_task(_current_task.take().unwrap()),
|
||||
TaskState::IDLE => *IDLE_TASK.lock() = _current_task.take(),
|
||||
TaskState::TERMINATED => destroy_task(_current_task.take().unwrap()),
|
||||
{
|
||||
let mut _current_task = CURRENT_TASK.lock();
|
||||
if let Some(current_task) = _current_task.as_mut() {
|
||||
current_task.state = *current_state;
|
||||
match current_task.task_state {
|
||||
TaskState::READY => schedule_task(_current_task.take().unwrap()),
|
||||
TaskState::IDLE => *IDLE_TASK.lock() = _current_task.take(),
|
||||
TaskState::TERMINATED => destroy_task(_current_task.take().unwrap()),
|
||||
}
|
||||
}
|
||||
*current_state = new_task.state;
|
||||
*_current_task = Some(new_task);
|
||||
schedule_timer_interrupt();
|
||||
}
|
||||
*current_state = new_task.state;
|
||||
*_current_task = Some(new_task);
|
||||
schedule_timer_interrupt();
|
||||
unlock_kernel();
|
||||
}
|
||||
pub fn create_task(func: fn()) -> Task {
|
||||
let stack_address = allocate_stack();
|
||||
let task = Task {
|
||||
id: NEXT_TASK_ID.fetch_add(1, Ordering::Relaxed),
|
||||
state: ISRState {
|
||||
rax: 0,
|
||||
rbx: 0,
|
||||
|
@ -86,7 +95,7 @@ pub fn create_task(func: fn()) -> Task {
|
|||
error_code: 0,
|
||||
rip: task_entry as u64,
|
||||
cs: 8,
|
||||
rflags: RFLAGS.load(core::sync::atomic::Ordering::Relaxed),
|
||||
rflags: RFLAGS.load(Ordering::Relaxed),
|
||||
rsp: stack_address,
|
||||
ss: 16,
|
||||
},
|
||||
|
@ -131,6 +140,7 @@ pub fn setup_multitasking() -> ! {
|
|||
}
|
||||
let task = create_task(main);
|
||||
schedule_task(task);
|
||||
MULTITASKING_ENABLED.store(true, Ordering::Relaxed);
|
||||
yield_task();
|
||||
panic!("Setting up multitasking failed");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue