Compare commits

..

No commits in common. "1bb4074e2f71145ec824f0dd8f99b278417a8112" and "6e64101d099f95e948ccfd77213dca8beabc54e0" have entirely different histories.

6 changed files with 31 additions and 174 deletions

@ -2,8 +2,6 @@ use crate::drivers::vga::{self, Color, ColorCode};
use crate::hlt_loop; use crate::hlt_loop;
use crate::memory::gdt; use crate::memory::gdt;
use crate::println; use crate::println;
use core::arch::asm;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use pic::{ use pic::{
disk1_interrupt_handler, disk2_interrupt_handler, init_pic, keyboard_interrupt_handler, disk1_interrupt_handler, disk2_interrupt_handler, init_pic, keyboard_interrupt_handler,
@ -14,8 +12,6 @@ use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame};
pub mod pic; pub mod pic;
const SYSCALL_32_INTERRUPT_NUMBER: usize = 0x80;
lazy_static! { lazy_static! {
static ref IDT: InterruptDescriptorTable = { static ref IDT: InterruptDescriptorTable = {
let mut idt = InterruptDescriptorTable::new(); let mut idt = InterruptDescriptorTable::new();
@ -30,7 +26,6 @@ lazy_static! {
idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler); idt[InterruptIndex::Keyboard.as_usize()].set_handler_fn(keyboard_interrupt_handler);
idt[InterruptIndex::HardDisk1.as_usize()].set_handler_fn(disk1_interrupt_handler); idt[InterruptIndex::HardDisk1.as_usize()].set_handler_fn(disk1_interrupt_handler);
idt[InterruptIndex::HardDisk2.as_usize()].set_handler_fn(disk2_interrupt_handler); idt[InterruptIndex::HardDisk2.as_usize()].set_handler_fn(disk2_interrupt_handler);
idt[SYSCALL_32_INTERRUPT_NUMBER].set_handler_fn(syscall_handler_32);
idt idt
}; };
} }
@ -52,44 +47,6 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: InterruptStackFrame) {
vga::change_color(color); vga::change_color(color);
} }
extern "x86-interrupt" fn syscall_handler_32(_stack_frame: InterruptStackFrame) {
let rax: u64;
let rbx: u64;
let rcx: u64;
let rdx: u64;
let rsi: u64;
let rdi: u64;
let rbp: u64;
unsafe {
asm!(
"push rax",
"push rbx",
"push rcx",
"push rdx",
"push rsi",
"push rdi",
"push rbp",
"pop {rbp}",
"pop {rdi}",
"pop {rsi}",
"pop {rdx}",
"pop {rcx}",
"pop {rbx}",
"pop {rax}",
rax = out(reg) rax,
rbx = out(reg) rbx,
rcx = out(reg) rcx,
rdx = out(reg) rdx,
rsi = out(reg) rsi,
rdi = out(reg) rdi,
rbp = out(reg) rbp,
)
}
println!("Received syscall");
crate::syscalls::syscall_routine(rax);
}
extern "x86-interrupt" fn page_fault_handler( extern "x86-interrupt" fn page_fault_handler(
stack_frame: InterruptStackFrame, stack_frame: InterruptStackFrame,
error_code: PageFaultErrorCode, error_code: PageFaultErrorCode,

@ -1,4 +1,3 @@
use crate::println;
use crate::utils::mutex::AsyncMutex; use crate::utils::mutex::AsyncMutex;
use super::thread::{Thread, ThreadId}; use super::thread::{Thread, ThreadId};
@ -24,7 +23,7 @@ pub const K_THREAD_ID: ThreadId = ThreadId(0); // Kernel main thread identifier
struct ThreadStream { struct ThreadStream {
ids: ArrayQueue<ThreadId>, ids: ArrayQueue<ThreadId>,
waker: AtomicWaker, waker: AtomicWaker
} }
impl ThreadStream { impl ThreadStream {
@ -36,7 +35,9 @@ impl ThreadStream {
} }
pub fn register(&mut self, id: ThreadId) { pub fn register(&mut self, id: ThreadId) {
self.ids.push(id).expect("Thread queue full"); self.ids
.push(id)
.expect("Thread queue full");
self.waker.wake(); self.waker.wake();
} }
} }
@ -78,32 +79,22 @@ impl Scheduler {
started: true, started: true,
rsp: 0, rsp: 0,
base_stack: 0, base_stack: 0,
is_blocked: false,
}; };
res.register(Arc::new(RefCell::new(k_thread))); res.register(Arc::new(RefCell::new(k_thread)));
res res
} }
pub async fn run(&mut self) { pub async fn run(&mut self) {
while let Some(id) = self.thread_queue.next().await { while let Some(id) = self.thread_queue.next().await {
if let Some(thread) = self.get_thread(id) { if let Some(thread) = self.get_thread(id) { // Thread still exists
// Thread still exists
let blocked: bool;
{
blocked = thread.borrow().is_blocked;
} // Drop thread borrow
if !blocked {
unsafe { unsafe {
(&mut *thread.as_ptr()).run(); (&mut*thread.as_ptr()).run();
} }
if !thread.borrow().is_blocked {
self.thread_queue.register(id); self.thread_queue.register(id);
} }
} }
} }
}
}
pub fn register(&mut self, thread: Threadt) { pub fn register(&mut self, thread: Threadt) {
let thread_id = thread.borrow().id; let thread_id = thread.borrow().id;
@ -115,21 +106,6 @@ impl Scheduler {
} }
} }
pub fn block(&mut self, id: ThreadId) {
if let Some(thread) = self.get_thread(id) {
thread.borrow_mut().is_blocked = true;
println!("Blocked thread {:?}", id);
}
}
pub fn unblock(&mut self, id: ThreadId) {
if let Some(thread) = self.get_thread(id) {
thread.borrow_mut().is_blocked = false;
self.thread_queue.register(id);
println!("Unblocked thread {:?}", id);
}
}
pub fn exit(&mut self, id: ThreadId) { pub fn exit(&mut self, id: ThreadId) {
self.threads.remove(&id).unwrap().borrow().exit(); self.threads.remove(&id).unwrap().borrow().exit();
} }

@ -1,7 +1,7 @@
use crate::println; use crate::println;
use crate::utils::mutex::AsyncMutex; use crate::utils::mutex::AsyncMutex;
use super::scheduler::{K_THREAD_ID, SCHEDULER}; use super::scheduler::{SCHEDULER, K_THREAD_ID};
use core::arch::asm; use core::arch::asm;
use core::sync::atomic::{AtomicU64, Ordering}; use core::sync::atomic::{AtomicU64, Ordering};
@ -25,22 +25,34 @@ impl ThreadId {
} }
} }
pub fn exit() {
println!("Exiting thread");
{
let mut scheduler = SCHEDULER.try_lock().unwrap();
scheduler.exit(*RUNNING_THREAD.try_lock().unwrap());
} // Drop scheduler mutex guard
resume_k_thread();
}
pub fn resume_k_thread() { pub fn resume_k_thread() {
let k_thread: *mut Thread; let k_thread: *mut Thread;
{ {
let mut scheduler = SCHEDULER.try_lock().unwrap(); let mut scheduler = SCHEDULER.try_lock().unwrap();
k_thread = scheduler.get_thread(K_THREAD_ID).unwrap().as_ptr(); k_thread = scheduler
.get_thread(K_THREAD_ID)
.unwrap()
.as_ptr();
} // Drop scheduler mutex guard } // Drop scheduler mutex guard
unsafe { unsafe {
(&mut *k_thread).run(); (&mut* k_thread).run();
} }
} }
pub fn routine() { pub fn routine() {
println!("Routine executed"); println!("Routine executed");
crate::syscalls::syscall_routine(crate::syscalls::EXIT_ID); // Call exit exit();
println!("SHOULD NEVER BE DISPLAYED");
} }
pub struct Thread { pub struct Thread {
@ -48,8 +60,7 @@ pub struct Thread {
pub entry_point: u64, pub entry_point: u64,
pub started: bool, pub started: bool,
pub rsp: u64, pub rsp: u64,
pub base_stack: u64, pub base_stack: u64
pub is_blocked: bool,
} }
impl Thread { impl Thread {
@ -62,17 +73,13 @@ impl Thread {
started: false, started: false,
rsp: stack_bottom + STACK_SIZE as u64, rsp: stack_bottom + STACK_SIZE as u64,
base_stack: stack_bottom, base_stack: stack_bottom,
is_blocked: false
} }
} }
} }
pub fn exit(&self) { pub fn exit(&self) {
unsafe { unsafe {
dealloc( dealloc(self.base_stack as *mut u8, Layout::new::<[u8; STACK_SIZE]>());
self.base_stack as *mut u8,
Layout::new::<[u8; STACK_SIZE]>(),
);
} }
} }
@ -91,8 +98,8 @@ impl Thread {
out = out(reg) current_rsp, // Save thread rsp out = out(reg) current_rsp, // Save thread rsp
); );
current_thread.borrow_mut().rsp = current_rsp; current_thread.borrow_mut().rsp = current_rsp;
} else { }
// Thread does not exists anymore else { // Thread does not exists anymore
*current_thread_guard = self.id; // change running thread *current_thread_guard = self.id; // change running thread
asm!( // Just switch to new thead without saving registers asm!( // Just switch to new thead without saving registers
"push {rsp}", // Set stack pointer to the new thread "push {rsp}", // Set stack pointer to the new thread

@ -1,3 +0,0 @@
pub type SyscallId = u64;
pub const EXIT_ID: u64 = 0;

@ -1,71 +1 @@
use crate::println;
use crate::proc::thread::{resume_k_thread, RUNNING_THREAD};
use crate::proc::scheduler::SCHEDULER;
use crate::task::executor::EXECUTOR;
use crate::task::Task;
pub use ids::*;
use alloc::sync::Arc;
use core::cell::RefCell;
pub mod ids;
pub mod io; pub mod io;
pub mod proc;
pub type SyscallContextT = Arc<RefCell<SyscallContext>>;
pub struct SyscallContext {
id: SyscallId,
res: u64,
thread_id: crate::proc::thread::ThreadId,
}
impl SyscallContext {
pub async fn run(&mut self) {
println!("Running async syscall runner");
self.dispatch().await;
println!("Syscall end, unblocking thread");
SCHEDULER.lock().await.unblock(self.thread_id);
}
pub async fn dispatch(&mut self) {
match self.id {
EXIT_ID => proc::exit(self).await,
_ => bad_syscall().await,
}
}
}
async fn syscall_runner(context: SyscallContextT) {
context.borrow_mut().run().await;
}
pub fn syscall_routine(syscall_id: SyscallId) -> u64 {
println!("Running syscall");
let context: SyscallContextT = Arc::new(RefCell::new(SyscallContext {
id: syscall_id,
res: 0,
thread_id: *RUNNING_THREAD.try_lock().unwrap(),
}));
println!("Spawning async syscall runner");
EXECUTOR
.try_lock()
.unwrap()
.spawn(Task::new(syscall_runner(context.clone())));
println!("Blocking thread");
SCHEDULER
.try_lock()
.unwrap()
.block(context.borrow().thread_id);
println!("Returning to scheduler");
resume_k_thread();
let res = context.borrow().res;
res
}
async fn bad_syscall() {}

@ -1,10 +0,0 @@
use crate::println;
use crate::proc::scheduler::SCHEDULER;
use super::SyscallContext;
pub async fn exit(context: &SyscallContext) {
println!("Running exit(2)");
let mut scheduler = SCHEDULER.lock().await;
scheduler.exit(context.thread_id);
}