From 3732a8983239c5edf57682ac82e5de7b7b80e690 Mon Sep 17 00:00:00 2001 From: GZTimeWalker Date: Thu, 12 May 2022 17:35:14 +0800 Subject: [PATCH] wip: pid & async test --- Cargo.lock | 37 ++++++++ pkg/kernel/Cargo.toml | 1 + pkg/kernel/src/drivers/console.rs | 19 +---- pkg/kernel/src/drivers/input.rs | 14 ++- pkg/kernel/src/drivers/mod.rs | 2 +- pkg/kernel/src/interrupt/keyboard.rs | 4 +- pkg/kernel/src/interrupt/serial.rs | 7 +- pkg/kernel/src/interrupt/syscall/mod.rs | 4 +- pkg/kernel/src/interrupt/syscall/service.rs | 9 +- pkg/kernel/src/lib.rs | 4 +- pkg/kernel/src/main.rs | 21 +++-- pkg/kernel/src/process/manager.rs | 26 ++---- pkg/kernel/src/process/mod.rs | 30 ++++++- pkg/kernel/src/process/process.rs | 13 +-- pkg/kernel/src/process/scheduler.rs | 3 +- pkg/kernel/src/tasks/executor.rs | 95 +++++++++++++++++++++ pkg/kernel/src/tasks/input.rs | 66 ++++++++++++++ pkg/kernel/src/tasks/mod.rs | 40 +++++++++ pkg/kernel/src/utils/resource.rs | 26 ++---- pkg/lib/src/io.rs | 15 ++-- 20 files changed, 332 insertions(+), 104 deletions(-) create mode 100644 pkg/kernel/src/tasks/executor.rs create mode 100644 pkg/kernel/src/tasks/input.rs create mode 100644 pkg/kernel/src/tasks/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 3979203..2e55891 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,6 +115,30 @@ dependencies = [ "num-traits", ] +[[package]] +name = "futures-core" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" + +[[package]] +name = "futures-task" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" + +[[package]] +name = "futures-util" +version = "0.3.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + [[package]] name = "ggfs" version = "0.1.0" @@ -172,6 +196,7 @@ dependencies = [ "chrono", "crossbeam-queue", "embedded-graphics", + "futures-util", "ggfs", "ggos_boot", "ggos_elf", @@ -312,6 +337,18 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6f2d937e3b8d63449b01401e2bae4041bc9dd1129c2e3e0d239407cf6635ac" +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro2" version = "1.0.37" diff --git a/pkg/kernel/Cargo.toml b/pkg/kernel/Cargo.toml index 2889156..6b09bf2 100644 --- a/pkg/kernel/Cargo.toml +++ b/pkg/kernel/Cargo.toml @@ -27,3 +27,4 @@ crossbeam-queue = { version = "0.3.5", default-features = false, features = ["al volatile = "0.4.4" xmas-elf = "0.8" num_enum = { version = "0.5.7", default-features = false } +futures-util = { version = "0.3.21", default-features = false, features = ["alloc"] } diff --git a/pkg/kernel/src/drivers/console.rs b/pkg/kernel/src/drivers/console.rs index a217bd0..a7a16ed 100644 --- a/pkg/kernel/src/drivers/console.rs +++ b/pkg/kernel/src/drivers/console.rs @@ -1,8 +1,6 @@ use crate::drivers::display::get_display_for_sure; -use crate::input::get_input_buf_for_sure; use crate::utils::colors; use crate::utils::font; -use alloc::string::ToString; use core::fmt::Write; use embedded_graphics::{ mono_font::{MonoFont, MonoTextStyle}, @@ -11,7 +9,6 @@ use embedded_graphics::{ text::{renderer::CharacterStyle, Baseline, Text}, }; use fs::*; -use pc_keyboard::DecodedKey; once_mutex!(pub CONSOLE: Console); @@ -184,20 +181,8 @@ impl Device for Console { if offset + size >= buf.len() { return Err(DeviceError::ReadError); } - x86_64::instructions::interrupts::without_interrupts(|| { - let stdin = get_input_buf_for_sure(); - let mut read_count = 0; - while !stdin.is_empty() && read_count < size { - if let Some(DecodedKey::Unicode(c)) = stdin.pop() { - let s = c.to_string(); - let len = s.len(); - buf[offset + read_count..offset + read_count + len] - .copy_from_slice(s.as_bytes()); - read_count += len; - } - } - Ok(read_count) - }) + // TODO: get key + Ok(0) } fn write(&mut self, buf: &[u8], offset: usize, size: usize) -> Result { diff --git a/pkg/kernel/src/drivers/input.rs b/pkg/kernel/src/drivers/input.rs index fd4ddb0..5b2242d 100644 --- a/pkg/kernel/src/drivers/input.rs +++ b/pkg/kernel/src/drivers/input.rs @@ -18,20 +18,18 @@ pub fn init() { pub fn try_get_key() -> Option { interrupts::without_interrupts(|| { if let Some(key) = get_input_buf_for_sure().pop() { - return Some(key); + Some(key) + } else { + None } - None }) } pub fn get_key() -> DecodedKey { loop { - crate::utils::halt(); - interrupts::without_interrupts(|| { - if let Some(k) = try_get_key() { - return k; - } - }) + if let Some(k) = try_get_key() { + return k; + } } } diff --git a/pkg/kernel/src/drivers/mod.rs b/pkg/kernel/src/drivers/mod.rs index 587c604..fecaf70 100644 --- a/pkg/kernel/src/drivers/mod.rs +++ b/pkg/kernel/src/drivers/mod.rs @@ -5,6 +5,6 @@ pub mod serial; pub mod console; pub mod display; pub mod keyboard; -pub mod input; +// pub mod input; pub mod filesystem; pub mod ata; diff --git a/pkg/kernel/src/interrupt/keyboard.rs b/pkg/kernel/src/interrupt/keyboard.rs index a49d107..5276c85 100644 --- a/pkg/kernel/src/interrupt/keyboard.rs +++ b/pkg/kernel/src/interrupt/keyboard.rs @@ -4,7 +4,7 @@ use x86_64::{ structures::idt::{InterruptDescriptorTable, InterruptStackFrame}, }; use pc_keyboard::DecodedKey; -use crate::{keyboard::get_keyboard_for_sure, drivers::input::get_input_buf_for_sure}; +use crate::{keyboard::get_keyboard_for_sure, push_key}; pub unsafe fn reg_idt(idt: &mut InterruptDescriptorTable) { idt[(consts::Interrupts::IRQ0 as u8 + consts::IRQ::Keyboard as u8) as usize] @@ -38,6 +38,6 @@ pub fn receive() -> Option { pub extern "x86-interrupt" fn interrupt_handler(_st: InterruptStackFrame) { super::ack(super::consts::IRQ::Keyboard as u8); if let Some(key) = receive() { - get_input_buf_for_sure().push(key).unwrap(); + push_key(key); } } diff --git a/pkg/kernel/src/interrupt/serial.rs b/pkg/kernel/src/interrupt/serial.rs index 5474a80..d92e219 100644 --- a/pkg/kernel/src/interrupt/serial.rs +++ b/pkg/kernel/src/interrupt/serial.rs @@ -1,10 +1,7 @@ use super::consts; use x86_64::structures::idt::{InterruptDescriptorTable, InterruptStackFrame}; use pc_keyboard::DecodedKey; -use crate::drivers::{ - input::get_input_buf_for_sure, - serial::get_serial_for_sure -}; +use crate::{drivers::serial::get_serial_for_sure, push_key}; pub unsafe fn reg_idt(idt: &mut InterruptDescriptorTable) { idt[(consts::Interrupts::IRQ0 as u8 + consts::IRQ::Serial0 as u8) as usize] @@ -33,6 +30,6 @@ pub fn receive() -> Option { pub extern "x86-interrupt" fn interrupt_handler(_st: InterruptStackFrame) { super::ack(super::consts::IRQ::Serial0 as u8); if let Some(key) = receive() { - get_input_buf_for_sure().push(key).unwrap(); + push_key(key); } } diff --git a/pkg/kernel/src/interrupt/syscall/mod.rs b/pkg/kernel/src/interrupt/syscall/mod.rs index b316604..33f7704 100644 --- a/pkg/kernel/src/interrupt/syscall/mod.rs +++ b/pkg/kernel/src/interrupt/syscall/mod.rs @@ -40,8 +40,6 @@ pub fn dispatcher(regs: &mut Registers, sf: &mut InterruptStackFrame) { regs.rsi, regs.rdx ); - debug!("{}", args); - debug!("{:#?}\n{:#?}", sf, regs); match args.syscall { Syscall::SpawnProcess => regs.set_rax(spawn_process(&args)), @@ -58,7 +56,7 @@ pub fn dispatcher(regs: &mut Registers, sf: &mut InterruptStackFrame) { Syscall::Draw => sys_draw(&args), Syscall::None => {} } - debug!("syscall finished."); + // debug!("syscall finished."); } impl SyscallArgs { diff --git a/pkg/kernel/src/interrupt/syscall/service.rs b/pkg/kernel/src/interrupt/syscall/service.rs index 758aab3..5caf9c1 100644 --- a/pkg/kernel/src/interrupt/syscall/service.rs +++ b/pkg/kernel/src/interrupt/syscall/service.rs @@ -65,7 +65,7 @@ pub fn spawn_process(args: &SyscallArgs) -> usize { warn!("spawn_process: failed to spawn process: {}", path); return 0; } - pid.unwrap() as usize + u16::from(pid.unwrap()) as usize } pub fn sys_read(args: &SyscallArgs) -> usize { @@ -74,12 +74,7 @@ pub fn sys_read(args: &SyscallArgs) -> usize { let buf = unsafe { core::slice::from_raw_parts_mut(args.arg1 as *mut u8, args.arg2) }; - return if let Ok(size) = res.read(buf) { - debug!( - "read {} bytes: {:?}", - size, - unsafe{ core::str::from_utf8_unchecked(&buf[..size]) } - ); + if let Ok(size) = res.read(buf) { size } else { 0 diff --git a/pkg/kernel/src/lib.rs b/pkg/kernel/src/lib.rs index 81c8d6c..1e868fb 100644 --- a/pkg/kernel/src/lib.rs +++ b/pkg/kernel/src/lib.rs @@ -25,6 +25,9 @@ pub mod drivers; pub use drivers::*; pub mod memory; +pub mod tasks; + +pub use tasks::*; use memory::gdt; use memory::allocator; @@ -48,7 +51,6 @@ pub fn init(boot_info: &'static BootInfo) { allocator::init(); // init heap allocator process::init(); // init process manager keyboard::init(); // init keyboard - input::init(); // init input manager ata::init(); // init ata filesystem::init(); // init filesystem diff --git a/pkg/kernel/src/main.rs b/pkg/kernel/src/main.rs index c8baf67..6127588 100644 --- a/pkg/kernel/src/main.rs +++ b/pkg/kernel/src/main.rs @@ -1,6 +1,7 @@ #![no_std] #![no_main] +use ggos::*; use ggos_kernel as ggos; extern crate alloc; @@ -10,14 +11,18 @@ boot::entry_point!(kernal_main); pub fn kernal_main(boot_info: &'static boot::BootInfo) -> ! { ggos::init(boot_info); - let sh_file = ggos::filesystem::try_get_file("/APP/SH").unwrap(); - let pid = ggos::process::spawn(&sh_file).unwrap(); + // let sh_file = ggos::filesystem::try_get_file("/APP/SH").unwrap(); + // let pid = ggos::process::spawn(&sh_file).unwrap(); - while ggos::process::still_alive(pid) { - unsafe { - core::arch::asm!("hlt"); - } - } + // while ggos::process::still_alive(pid) { + // unsafe { + // core::arch::asm!("hlt"); + // } + // } - ggos::shutdown(boot_info); + let mut executor = Executor::new(); + executor.spawn(Task::new(get_key())); + executor.run(); + + // ggos::shutdown(boot_info); } diff --git a/pkg/kernel/src/process/manager.rs b/pkg/kernel/src/process/manager.rs index a52258f..2648663 100644 --- a/pkg/kernel/src/process/manager.rs +++ b/pkg/kernel/src/process/manager.rs @@ -12,10 +12,8 @@ guard_access_fn! { } pub struct ProcessManager { - /// the next pid to be assigned - next_pid: u16, /// pid of the current running process - cur_pid: u16, + cur_pid: ProcessId, processes: Vec, } @@ -24,8 +22,7 @@ impl ProcessManager { let mut processes = Vec::::new(); processes.push(init); Self { - cur_pid: 0, - next_pid: 1, + cur_pid: ProcessId(0), processes, } } @@ -50,7 +47,7 @@ impl ProcessManager { current.tick(); current.save(regs, sf); } - debug!("Paused process #{}", self.cur_pid); + // debug!("Paused process #{}", self.cur_pid); } fn get_next_pos(&self) -> usize { @@ -67,7 +64,7 @@ impl ProcessManager { } } - pub fn still_alive(&self, pid: u16) -> bool { + pub fn still_alive(&self, pid: ProcessId) -> bool { self.processes.iter().any(|x| x.pid() == pid) } @@ -75,7 +72,7 @@ impl ProcessManager { let pos = self.get_next_pos(); let p = &mut self.processes[pos]; - debug!("Next process {} #{}", p.name(), p.pid()); + // debug!("Next process {} #{}", p.name(), p.pid()); if p.pid() == self.cur_pid { // the next process to be resumed is the same as the current one p.resume(); @@ -90,12 +87,11 @@ impl ProcessManager { &mut self, elf: &ElfFile, name: String, - parent: u16, + parent: ProcessId, proc_data: Option, - ) -> u16 { + ) -> ProcessId { let mut p = Process::new( &mut *crate::memory::get_frame_alloc_for_sure(), - self.next_pid, name, parent, proc_data, @@ -110,7 +106,6 @@ impl ProcessManager { // info!("Spawn process:\n\n{:?}\n", p); let pid = p.pid(); self.processes.push(p); - self.next_pid += 1; // TODO: recycle PID pid } @@ -119,12 +114,11 @@ impl ProcessManager { entry: VirtAddr, stack_top: VirtAddr, name: String, - parent: u16, + parent: ProcessId, proc_data: Option, - ) -> u16 { + ) -> ProcessId { let mut p = Process::new( &mut *crate::memory::get_frame_alloc_for_sure(), - self.next_pid, name, parent, proc_data, @@ -132,10 +126,8 @@ impl ProcessManager { p.pause(); p.init_stack_frame(entry, stack_top); info!("Spawn process: {}#{}", p.name(), p.pid()); - // info!("Spawn process:\n\n{:?}\n", p); let pid = p.pid(); self.processes.push(p); - self.next_pid += 1; // TODO: recycle PID pid } diff --git a/pkg/kernel/src/process/mod.rs b/pkg/kernel/src/process/mod.rs index 94881ea..a76a6a0 100644 --- a/pkg/kernel/src/process/mod.rs +++ b/pkg/kernel/src/process/mod.rs @@ -2,6 +2,8 @@ mod manager; mod process; mod scheduler; +use core::sync::atomic::{AtomicU16, Ordering}; + use fs::File; use manager::*; use process::*; @@ -28,11 +30,33 @@ pub enum ProgramStatus { Dead, } +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct ProcessId(u16); + +impl ProcessId { + pub fn new() -> Self { + static NEXT_PID: AtomicU16 = AtomicU16::new(0); + ProcessId(NEXT_PID.fetch_add(1, Ordering::Relaxed)) + } +} + +impl core::fmt::Display for ProcessId { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From for u16 { + fn from(pid: ProcessId) -> Self { + pid.0 + } +} + /// init process manager pub fn init() { let mut alloc = crate::memory::get_frame_alloc_for_sure(); // kernel process - let mut kproc = Process::new(&mut *alloc, 0, String::from("kernel"), 0, None); + let mut kproc = Process::new(&mut *alloc, String::from("kernel"), ProcessId(0), None); kproc.resume(); kproc.set_page_table_with_cr3(); init_PROCESS_MANAGER(ProcessManager::new(kproc)); @@ -66,13 +90,13 @@ pub fn handle(fd: u8) -> Option { }) } -pub fn still_alive(pid: u16) -> bool { +pub fn still_alive(pid: ProcessId) -> bool { x86_64::instructions::interrupts::without_interrupts(|| { get_process_manager_for_sure().still_alive(pid) }) } -pub fn spawn(file: &File) -> Result { +pub fn spawn(file: &File) -> Result { let size = file.length(); let data = { let pages = (size as usize + 0x1000 - 1) / 0x1000; diff --git a/pkg/kernel/src/process/process.rs b/pkg/kernel/src/process/process.rs index abdc14d..ea33361 100644 --- a/pkg/kernel/src/process/process.rs +++ b/pkg/kernel/src/process/process.rs @@ -14,15 +14,16 @@ use x86_64::structures::paging::FrameAllocator; use x86_64::structures::paging::{OffsetPageTable, PageTable, PhysFrame}; use x86_64::VirtAddr; use xmas_elf::ElfFile; +use super::ProcessId; pub struct Process { - pid: u16, + pid: ProcessId, regs: RegistersValue, name: String, - parent: u16, + parent: ProcessId, status: ProgramStatus, ticks_passed: usize, - children: Vec, + children: Vec, stack_frame: InterruptStackFrameValue, page_table_addr: (PhysFrame, Cr3Flags), page_table: Option>, @@ -53,7 +54,7 @@ impl ProcessData { } impl Process { - pub fn pid(&self) -> u16 { + pub fn pid(&self) -> ProcessId { self.pid } @@ -117,9 +118,8 @@ impl Process { pub fn new( frame_alloc: &mut BootInfoFrameAllocator, - pid: u16, name: String, - parent: u16, + parent: ProcessId, proc_data: Option, ) -> Self { // 1. alloc a page table for process @@ -162,6 +162,7 @@ impl Process { }; let regs = RegistersValue::default(); let ticks_passed = 0; + let pid = ProcessId::new(); debug!("New process {}#{} created.", name, pid); diff --git a/pkg/kernel/src/process/scheduler.rs b/pkg/kernel/src/process/scheduler.rs index fd23d3d..c8cd9fa 100644 --- a/pkg/kernel/src/process/scheduler.rs +++ b/pkg/kernel/src/process/scheduler.rs @@ -5,6 +5,7 @@ use alloc::string::String; use crate::memory::*; use crate::utils::Registers; use crate::process::ProcessData; +use super::ProcessId; use super::manager::get_process_manager_for_sure; pub fn switch(regs: &mut Registers, sf: &mut InterruptStackFrame) { @@ -27,6 +28,6 @@ pub fn spawn_kernel_thread(entry: fn() -> !, name: String, data: Option, + task_queue: Arc>, + waker_cache: BTreeMap, +} + +impl Executor { + pub fn new() -> Self { + Executor { + tasks: BTreeMap::new(), + task_queue: Arc::new(ArrayQueue::new(128)), + waker_cache: BTreeMap::new(), + } + } + + pub fn spawn(&mut self, task: Task) { + let task_id = task.id; + if self.tasks.insert(task.id, task).is_some() { + panic!("task with same ID already in tasks"); + } + self.task_queue.push(task_id).expect("queue full"); + } + + pub fn run(&mut self) -> ! { + loop { + self.run_ready_tasks(); + self.sleep_if_idle(); + } + } + + fn run_ready_tasks(&mut self) { + while let Some(task_id) = self.task_queue.pop() { + let task = match self.tasks.get_mut(&task_id) { + Some(task) => task, + None => continue, // task no longer exists + }; + let waker = self.waker_cache + .entry(task_id) + .or_insert_with(|| TaskWaker::new(task_id, self.task_queue.clone())); + let mut context = Context::from_waker(waker); + match task.poll(&mut context) { + Poll::Ready(()) => { + // task done -> remove it and its cached waker + self.tasks.remove(&task_id); + self.waker_cache.remove(&task_id); + } + Poll::Pending => {} + } + } + } + + fn sleep_if_idle(&self) { + use x86_64::instructions::interrupts::{self, enable_and_hlt}; + + interrupts::disable(); + if self.task_queue.is_empty() { + enable_and_hlt(); + } else { + interrupts::enable(); + } + } +} + +struct TaskWaker { + task_id: TaskId, + task_queue: Arc>, +} + +impl TaskWaker { + fn new(task_id: TaskId, task_queue: Arc>) -> Waker { + Waker::from(Arc::new(TaskWaker { + task_id, + task_queue, + })) + } + + fn wake_task(&self) { + self.task_queue.push(self.task_id).expect("task_queue full"); + } +} + +impl Wake for TaskWaker { + fn wake(self: Arc) { + self.wake_task(); + } + + fn wake_by_ref(self: &Arc) { + self.wake_task(); + } +} diff --git a/pkg/kernel/src/tasks/input.rs b/pkg/kernel/src/tasks/input.rs new file mode 100644 index 0000000..399902a --- /dev/null +++ b/pkg/kernel/src/tasks/input.rs @@ -0,0 +1,66 @@ +use core::{ + pin::Pin, + task::{Context, Poll}, +}; +use crossbeam_queue::ArrayQueue; +use pc_keyboard::DecodedKey; +use futures_util::{ + stream::{Stream, StreamExt}, + task::AtomicWaker +}; + +once_mutex!(pub INPUT_QUEUE: ArrayQueue); + +const DEFAULT_BUF_SIZE: usize = 128; + +guard_access_fn!(pub get_input_queue(INPUT_QUEUE: ArrayQueue)); + +static INPUT_WAKER: AtomicWaker = AtomicWaker::new(); + +pub fn push_key(key: DecodedKey) { + if let Some(queue) = get_input_queue() { + if let Ok(_) = queue.push(key) { + INPUT_WAKER.wake() + } + } +} + +pub struct InputStream; + +impl InputStream { + pub fn new() -> Self { + init_INPUT_QUEUE(ArrayQueue::new(DEFAULT_BUF_SIZE)); + info!("Input stream Initialized."); + Self + } +} + +impl Stream for InputStream { + type Item = DecodedKey; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + let queue = get_input_queue_for_sure(); + if let Some(key) = queue.pop() { + Poll::Ready(Some(key)) + } else { + INPUT_WAKER.register(&cx.waker()); + match queue.pop() { + Some(key) => { + INPUT_WAKER.take(); + Poll::Ready(Some(key)) + } + None => Poll::Pending, + } + } + } +} + +pub async fn get_key() { + let mut input = InputStream::new(); + while let Some(key) = input.next().await { + match key { + DecodedKey::Unicode(c) => print!("{}", c), + DecodedKey::RawKey(k) => print!("{:?}", k), + } + } +} diff --git a/pkg/kernel/src/tasks/mod.rs b/pkg/kernel/src/tasks/mod.rs new file mode 100644 index 0000000..d0a860b --- /dev/null +++ b/pkg/kernel/src/tasks/mod.rs @@ -0,0 +1,40 @@ +use alloc::boxed::Box; +use core::{ + future::Future, + pin::Pin, + sync::atomic::{AtomicU64, Ordering}, + task::{Context, Poll}, +}; + +pub mod executor; +pub mod input; + +pub use input::{get_key, push_key}; +pub use executor::Executor; +pub struct Task { + id: TaskId, + future: Pin>>, +} + +impl Task { + pub fn new(future: impl Future + 'static) -> Task { + Task { + id: TaskId::new(), + future: Box::pin(future), + } + } + + fn poll(&mut self, context: &mut Context) -> Poll<()> { + self.future.as_mut().poll(context) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct TaskId(u64); + +impl TaskId { + fn new() -> Self { + static NEXT_ID: AtomicU64 = AtomicU64::new(0); + TaskId(NEXT_ID.fetch_add(1, Ordering::Relaxed)) + } +} diff --git a/pkg/kernel/src/utils/resource.rs b/pkg/kernel/src/utils/resource.rs index d1ea777..c3d8fca 100644 --- a/pkg/kernel/src/utils/resource.rs +++ b/pkg/kernel/src/utils/resource.rs @@ -1,7 +1,5 @@ -use crate::input; -use alloc::string::{String, ToString}; +use alloc::string::String; use fs::{Device, File, Random}; -use pc_keyboard::DecodedKey; use crate::filesystem::{get_volume, StdIO}; @@ -19,24 +17,12 @@ impl Resource { Resource::File(file) => fs::read_to_buf(get_volume(), file, buf).map_err(|_| ()), Resource::Console(stdio) => match stdio { &StdIO::Stdin => { - if buf.len() < 4 { - return Ok(0); - } - - let mut s = if buf.len() == 4 { - if let DecodedKey::Unicode(c) = input::get_key() { - c.to_string() - } else { - return Ok(0); - } + return if buf.len() < 4 { + Ok(0) } else { - input::get_line() - }; - - s.truncate(buf.len()); - let n = s.len(); - buf[..n].copy_from_slice(s.as_bytes()); - Ok(n) + // TODO: get key async + Ok(0) + } } _ => Err(()), }, diff --git a/pkg/lib/src/io.rs b/pkg/lib/src/io.rs index 09e6e2c..a2faa14 100644 --- a/pkg/lib/src/io.rs +++ b/pkg/lib/src/io.rs @@ -22,12 +22,17 @@ impl Stdin { } pub fn read_line(&self) -> String { - let mut buf = vec![0; 256]; - if let Some(bytes) = sys_read(0, &mut buf) { - String::from_utf8_lossy(&buf[..bytes]).to_string() - } else { - String::new() + let mut string = String::new(); + loop { + if let Some(bytes) = self.read_char() { + if bytes == '\n' { + break; + } else { + string.push(bytes); + } + } } + string } }