basic scheduler
All checks were successful
continuous-integration/drone/push Build is passing

Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
Julien CLEMENT 2022-12-31 13:21:42 +01:00
parent af4ab10505
commit 685dea4f6a
3 changed files with 69 additions and 21 deletions

@ -65,6 +65,7 @@ pub extern "C" fn julios_main(multiboot_info_addr: usize) -> ! {
executor.spawn(Task::new(drivers::atapi::init())); executor.spawn(Task::new(drivers::atapi::init()));
executor.spawn(Task::new(keyboard::print_keypresses())); executor.spawn(Task::new(keyboard::print_keypresses()));
executor.spawn(Task::new(get_file())); executor.spawn(Task::new(get_file()));
executor.spawn(Task::new(proc::scheduler::scheduler_run()));
executor.run(); executor.run();
} }
@ -89,14 +90,10 @@ async fn get_file() {
fd.borrow_mut().close().await; fd.borrow_mut().close().await;
let thread = Arc::new(RefCell::new(proc::thread::Thread::new( let thread = Arc::new(RefCell::new(proc::thread::Thread::new(
proc::thread::exit as u64, proc::thread::routine as u64,
))); )));
proc::scheduler::SCHEDULER proc::scheduler::SCHEDULER
.lock() .lock()
.await .await
.register(thread.clone()); .register(thread.clone());
unsafe {
(&mut*thread.as_ptr()).run();
}
} }

@ -4,7 +4,13 @@ use super::thread::{Thread, ThreadId};
use alloc::{collections::BTreeMap, sync::Arc}; use alloc::{collections::BTreeMap, sync::Arc};
use core::cell::RefCell; use core::cell::RefCell;
use core::{
pin::Pin,
task::{Context, Poll},
};
use crossbeam_queue::ArrayQueue; use crossbeam_queue::ArrayQueue;
use futures_util::stream::{Stream, StreamExt};
use futures_util::task::AtomicWaker;
use lazy_static::lazy_static; use lazy_static::lazy_static;
lazy_static! { lazy_static! {
@ -13,16 +19,50 @@ lazy_static! {
pub type Threadt = Arc<RefCell<Thread>>; pub type Threadt = Arc<RefCell<Thread>>;
struct ThreadStream {
ids: ArrayQueue<ThreadId>,
waker: AtomicWaker
}
impl ThreadStream {
pub fn new() -> Self {
ThreadStream {
ids: ArrayQueue::new(100),
waker: AtomicWaker::new(),
}
}
}
impl Stream for ThreadStream {
type Item = ThreadId;
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
if let Ok(id) = self.ids.pop() {
return Poll::Ready(Some(id));
}
self.waker.register(&cx.waker());
match self.ids.pop() {
Ok(id) => {
self.waker.take();
Poll::Ready(Some(id))
}
Err(crossbeam_queue::PopError) => Poll::Pending,
}
}
}
pub struct Scheduler { pub struct Scheduler {
pub threads: BTreeMap<ThreadId, Threadt>, pub threads: BTreeMap<ThreadId, Threadt>,
thread_queue: Arc<ArrayQueue<ThreadId>>, thread_queue: ThreadStream,
} }
impl Scheduler { impl Scheduler {
pub fn new() -> Self { pub fn new() -> Self {
let mut res = Scheduler { let mut res = Scheduler {
threads: BTreeMap::new(), threads: BTreeMap::new(),
thread_queue: Arc::new(ArrayQueue::new(100)), thread_queue: ThreadStream::new(),
}; };
let k_thread: Thread = Thread { let k_thread: Thread = Thread {
id: ThreadId(0), id: ThreadId(0),
@ -34,16 +74,13 @@ impl Scheduler {
res res
} }
pub fn schedule(&mut self) -> Option<Threadt> {
if let Ok(thread_id) = self.thread_queue.pop() { pub async fn run(&mut self) {
self.thread_queue.push(thread_id); while let Some(id) = self.thread_queue.next().await {
let thread = match self.threads.get_mut(&thread_id) { let thread = self.get_thread(id).unwrap();
Some(thread) => thread, unsafe {
None => return None, (&mut*thread.as_ptr()).run();
}; }
Some(thread.clone())
} else {
None
} }
} }
@ -53,8 +90,10 @@ impl Scheduler {
panic!("Duplicate thread ID") panic!("Duplicate thread ID")
} }
self.thread_queue self.thread_queue
.ids
.push(thread_id) .push(thread_id)
.expect("Thread queue full"); .expect("Thread queue full");
self.thread_queue.waker.wake();
} }
pub fn get_thread(&mut self, id: ThreadId) -> Option<Threadt> { pub fn get_thread(&mut self, id: ThreadId) -> Option<Threadt> {
@ -65,3 +104,9 @@ impl Scheduler {
} }
} }
} }
pub async fn scheduler_run() {
let mut scheduler = SCHEDULER.lock().await;
SCHEDULER.force_unlock();
scheduler.run().await;
}

@ -27,20 +27,25 @@ impl ThreadId {
pub fn exit() { pub fn exit() {
println!("Exiting thread"); println!("Exiting thread");
let thread: *mut Thread; let k_thread: *mut Thread;
{ {
let mut scheduler = SCHEDULER.try_lock().unwrap(); let mut scheduler = SCHEDULER.try_lock().unwrap();
thread = scheduler k_thread = scheduler
.get_thread(ThreadId(0)) .get_thread(ThreadId(0))
.unwrap() .unwrap()
.as_ptr(); .as_ptr();
} // Drop scheduler mutex guard } // Drop scheduler mutex guard
unsafe { unsafe {
(&mut* thread).run(); (&mut* k_thread).run();
} }
} }
pub fn routine() {
println!("Routine executed");
exit();
}
pub struct Thread { pub struct Thread {
pub id: ThreadId, pub id: ThreadId,
pub entry_point: u64, pub entry_point: u64,
@ -73,11 +78,12 @@ impl Thread {
); );
let mut scheduler = SCHEDULER.try_lock().unwrap(); let mut scheduler = SCHEDULER.try_lock().unwrap();
// TODO: check if the thread still exists
let current_thread = scheduler.get_thread(*current_thread_guard).unwrap(); let current_thread = scheduler.get_thread(*current_thread_guard).unwrap();
current_thread.borrow_mut().rsp = current_rsp; current_thread.borrow_mut().rsp = current_rsp;
*current_thread_guard = self.id; // change running thread *current_thread_guard = self.id; // change running thread
} // The scheduler and running thread guards is dropped here } // The scheduler and running thread guards are dropped here
unsafe { unsafe {
if self.started { if self.started {