Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
This commit is contained in:
parent
af4ab10505
commit
685dea4f6a
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user