All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: Julien CLEMENT <julien.clement@epita.fr>
112 lines
2.7 KiB
Rust
112 lines
2.7 KiB
Rust
use crate::utils::mutex::AsyncMutex;
|
|
|
|
use super::thread::{Thread, ThreadId};
|
|
|
|
use alloc::{collections::BTreeMap, sync::Arc};
|
|
use core::cell::RefCell;
|
|
use core::{
|
|
pin::Pin,
|
|
task::{Context, Poll},
|
|
};
|
|
use crossbeam_queue::ArrayQueue;
|
|
use futures_util::stream::{Stream, StreamExt};
|
|
use futures_util::task::AtomicWaker;
|
|
use lazy_static::lazy_static;
|
|
|
|
lazy_static! {
|
|
pub static ref SCHEDULER: AsyncMutex<Scheduler> = AsyncMutex::new(Scheduler::new());
|
|
}
|
|
|
|
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 threads: BTreeMap<ThreadId, Threadt>,
|
|
thread_queue: ThreadStream,
|
|
}
|
|
|
|
impl Scheduler {
|
|
pub fn new() -> Self {
|
|
let mut res = Scheduler {
|
|
threads: BTreeMap::new(),
|
|
thread_queue: ThreadStream::new(),
|
|
};
|
|
let k_thread: Thread = Thread {
|
|
id: ThreadId(0),
|
|
entry_point: 0,
|
|
started: true,
|
|
rsp: 0,
|
|
};
|
|
res.register(Arc::new(RefCell::new(k_thread)));
|
|
res
|
|
}
|
|
|
|
|
|
pub async fn run(&mut self) {
|
|
while let Some(id) = self.thread_queue.next().await {
|
|
let thread = self.get_thread(id).unwrap();
|
|
unsafe {
|
|
(&mut*thread.as_ptr()).run();
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn register(&mut self, thread: Threadt) {
|
|
let thread_id = thread.borrow().id;
|
|
if self.threads.insert(thread_id, thread).is_some() {
|
|
panic!("Duplicate thread ID")
|
|
}
|
|
self.thread_queue
|
|
.ids
|
|
.push(thread_id)
|
|
.expect("Thread queue full");
|
|
self.thread_queue.waker.wake();
|
|
}
|
|
|
|
pub fn get_thread(&mut self, id: ThreadId) -> Option<Threadt> {
|
|
if let Some(thread) = self.threads.get_mut(&id) {
|
|
Some(thread.clone())
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn scheduler_run() {
|
|
let mut scheduler = SCHEDULER.lock().await;
|
|
SCHEDULER.force_unlock();
|
|
scheduler.run().await;
|
|
} |