diff --git a/Cargo.lock b/Cargo.lock index c740678..73fa154 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,13 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "array-init" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "autocfg" version = "1.0.0" @@ -29,12 +21,9 @@ version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "cast" -version = "0.2.3" +name = "cfg-if" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "chrono" @@ -58,11 +47,62 @@ name = "compiler_builtins" version = "0.1.26" source = "git+https://github.com/rust-lang/compiler-builtins#72526f3811fa17babe3b37ca2e6371fa3786f06b" +[[package]] +name = "conquer-once" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "conquer-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "conquer-util" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cpuio" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "crossbeam-queue" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-utils" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "futures-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-task" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "futures-util" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -97,11 +137,6 @@ name = "memory_units" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "num-integer" version = "0.1.42" @@ -136,7 +171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pc-keyboard" -version = "0.3.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -148,31 +183,15 @@ dependencies = [ ] [[package]] -name = "rustc_version" -version = "0.2.3" +name = "pin-utils" +version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "spin" version = "0.5.2" @@ -195,11 +214,6 @@ dependencies = [ "x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ux" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "volatile" version = "0.2.6" @@ -226,18 +240,6 @@ dependencies = [ "parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "x86_64" -version = "0.7.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "x86_64" version = "0.9.6" @@ -255,50 +257,54 @@ dependencies = [ "chrono 0.4.9 (git+https://tulpa.dev/xeos/chrono)", "cmos 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "compiler_builtins 0.1.26 (git+https://github.com/rust-lang/compiler-builtins)", + "conquer-once 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "linked_list_allocator 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "uart_16550 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "wasmi 0.5.1 (git+https://tulpa.dev/xeos/wasmi)", - "x86_64 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [metadata] -"checksum array-init 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "23589ecb866b460d3a0f1278834750268c607e8e28a1b982c907219f3178cd72" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" "checksum bit_field 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ed8765909f9009617974ab6b7d332625b320b33c326b1e9321382ef1999b5d56" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum bootloader 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "152a28c753e229e037e910b4cd4cd16a90c53dd9a67fd751fa304b4b4a03970c" -"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum chrono 0.4.9 (git+https://tulpa.dev/xeos/chrono)" = "" "checksum cmos 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a5377a95644e12ea6460d19d59692c40a5fc65d0eb2ad34390c12cbb5a64095" "checksum compiler_builtins 0.1.26 (git+https://github.com/rust-lang/compiler-builtins)" = "" +"checksum conquer-once 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7644600a548ecad74e4a918392af1798f7dd045be610be3203b9e129b4f98f" +"checksum conquer-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "654fb2472cc369d311c547103a1fa81d467bef370ae7a0680f65939895b1182a" "checksum cpuio 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "22b8e308ccfc5acf3b82f79c0eac444cf6114cb2ac67a230ca6c177210068daa" +"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +"checksum futures-core 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a" +"checksum futures-task 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27" +"checksum futures-util 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libm 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a" "checksum linked_list_allocator 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5825aea823c659d0fdcdbe8c9b78baf56f3a10365d783db874f6d360df72626f" "checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" "checksum memory_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "71d96e3f3c0b6325d8ccd83c33b28acb183edcb6c67938ba104ec546854b0882" -"checksum nodrop 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" "checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" "checksum num-rational 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" "checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" "checksum parity-wasm 0.40.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1e39faaa292a687ea15120b1ac31899b13586446521df6c149e46f1584671e0f" -"checksum pc-keyboard 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fff50ab09ba31bcebc0669f4e64c0952fae1acdca9e6e0587e68e4e8443808ac" +"checksum pc-keyboard 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c48392db76c4e9a69e0b3be356c5f97ebb7b14413c5e4fd0af4755dbf86e2fce" "checksum pic8259_simple 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc64b2fd10828da8521b6cdabe0679385d7d2a3a6d4c336b819d1fa31ba35c72" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" "checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" "checksum spinning_top 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32d801a3a53bcf5071f85fef8d5cab9e5f638fc5580a37e6eb7aba4b37438d24" "checksum uart_16550 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d44b0f30cb82b0fbc15b78ade1064226529ad52028bc8cb8accb98ff6f3d7131" -"checksum ux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "88dfeb711b61ce620c0cb6fd9f8e3e678622f0c971da2a63c4b3e25e88ed012f" "checksum volatile 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "6af0edf5b4faacc31fc51159244d78d65ec580f021afcef7bd53c04aeabc7f29" "checksum wasmi 0.5.1 (git+https://tulpa.dev/xeos/wasmi)" = "" "checksum wasmi-validation 0.2.0 (git+https://tulpa.dev/xeos/wasmi)" = "" -"checksum x86_64 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1f27d9168654aee1b0c1b73746caeb4aa33248f8b8c8f6e100e697fcc2a794b2" "checksum x86_64 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4206b60c9f99766329b66962aa8ddc01df6c7edd02edc046b7a69d5df9fcdbcf" diff --git a/Cargo.toml b/Cargo.toml index 9cd711c..9eff643 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,10 +10,10 @@ edition = "2018" bootloader = { version = "0.8.0", features = ["map_physical_memory"]} volatile = "0.2.6" spin = "0.5.2" -x86_64 = "0.7.5" +x86_64 = "0.9.6" uart_16550 = "0.2.0" pic8259_simple = "0.1.1" -pc-keyboard = "0.3.1" +pc-keyboard = "0" linked_list_allocator = "0" wasmi = {git = "https://tulpa.dev/xeos/wasmi", default-features=false, features = ["core"] } compiler_builtins = { git = "https://github.com/rust-lang/compiler-builtins" } @@ -24,6 +24,20 @@ cmos = "0.1.1" version = "1.0" features = ["spin_no_std"] +[dependencies.crossbeam-queue] +version = "0.2.1" +default-features = false +features = ["alloc"] + +[dependencies.futures-util] +version = "0.3.4" +default-features = false +features = ["alloc"] + +[dependencies.conquer-once] +version = "0.2.0" +default-features = false + [profile.dev] panic = "abort" diff --git a/nix/rust.nix b/nix/rust.nix index 6bdf9eb..31348aa 100644 --- a/nix/rust.nix +++ b/nix/rust.nix @@ -4,8 +4,12 @@ let pkgs = import sources.nixpkgs { overlays = [ (import sources.nixpkgs-mozilla) ]; }; in (pkgs.rustChannelOf { - date = "2020-03-19"; + date = "2020-03-25"; channel = "nightly"; }).rust.override { - extensions = [ "rust-src" "rls-preview" "rustfmt-preview" ]; + extensions = [ + "rust-src" + # "rls-preview" + # "rustfmt-preview" + ]; } diff --git a/src/allocator.rs b/src/allocator.rs index 8ed50cb..44e73bb 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -36,8 +36,7 @@ pub const HEAP_SIZE: usize = 4 * 1024 * 1024; // 4 MiB pub fn init_heap( mapper: &mut impl Mapper, frame_allocator: &mut impl FrameAllocator, -) -> Result<(), MapToError> { - println!("[ ] creating heap"); +) -> Result<(), MapToError> { let page_range = { let heap_start = VirtAddr::new(HEAP_START as u64); let heap_end = heap_start + HEAP_SIZE - 1u64; @@ -51,14 +50,9 @@ pub fn init_heap( .allocate_frame() .ok_or(MapToError::FrameAllocationFailed)?; let flags = PageTableFlags::PRESENT | PageTableFlags::WRITABLE; - unsafe { mapper.map_to(page, frame, flags, frame_allocator)?.flush() }; + mapper.map_to(page, frame, flags, frame_allocator)?.flush(); } - unsafe { - ALLOCATOR.lock().init(HEAP_START, HEAP_SIZE); - } - - println!("[ ] heap created"); Ok(()) } diff --git a/src/interrupts.rs b/src/interrupts.rs index 9867425..9bb5d35 100644 --- a/src/interrupts.rs +++ b/src/interrupts.rs @@ -29,7 +29,7 @@ extern "x86-interrupt" fn breakpoint_handler(stack_frame: &mut InterruptStackFra extern "x86-interrupt" fn double_fault_handler( stack_frame: &mut InterruptStackFrame, _error_code: u64, -) { +) -> ! { panic!("EXCEPTION: DOUBLE FAULT\n{:#?}", stack_frame); } @@ -79,28 +79,14 @@ extern "x86-interrupt" fn timer_interrupt_handler(_stack_frame: &mut InterruptSt } } -extern "x86-interrupt" fn keyboard_interrupt_handler(_stack_frame: &mut InterruptStackFrame) { - use pc_keyboard::{layouts, DecodedKey, Keyboard, ScancodeSet1}; - use spin::Mutex; +extern "x86-interrupt" fn keyboard_interrupt_handler( + _stack_frame: &mut InterruptStackFrame +) { use x86_64::instructions::port::Port; - lazy_static! { - static ref KEYBOARD: Mutex> = - Mutex::new(Keyboard::new(layouts::Us104Key, ScancodeSet1)); - } - - let mut keyboard = KEYBOARD.lock(); let mut port = Port::new(0x60); - let scancode: u8 = unsafe { port.read() }; - if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { - if let Some(key) = keyboard.process_keyevent(key_event) { - match key { - DecodedKey::Unicode(character) => print!("{}", character), - DecodedKey::RawKey(key) => print!("{:?}", key), - } - } - } + crate::task::keyboard::add_scancode(scancode); // new unsafe { PICS.lock() diff --git a/src/lib.rs b/src/lib.rs index 0cf18bc..25b32cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,7 @@ #![feature(custom_test_frameworks)] #![feature(const_in_array_repeat_expressions)] #![feature(alloc_layout_extra)] +#![feature(wake_trait)] #![test_runner(crate::test_runner)] #![reexport_test_harness_main = "test_main"] @@ -17,6 +18,7 @@ pub mod gdt; pub mod interrupts; pub mod memory; pub mod serial; +pub mod task; pub mod vga_buffer; pub mod wasm; diff --git a/src/main.rs b/src/main.rs index 05523db..34df049 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ extern crate alloc; use alloc::string::ToString; use bootloader::{entry_point, BootInfo}; use core::panic::PanicInfo; -use xe_os::{clock, init, println, wasm}; +use xe_os::{clock, init, println, wasm, task::{Task, executor::Executor, keyboard}}; entry_point!(kernel_main); @@ -21,11 +21,15 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! { // Read the rtc date time using this year let now = clock::current_time(); - println!("now: {}", now.to_string()); + println!(" now: {}", now.to_string()); - println!("Running WASM:"); - wasm::run(); - println!("[ ] success"); + let mut executor = Executor::new(); + executor.spawn(Task::new(h_task())); + executor.spawn(Task::new(example_task())); + executor.spawn(Task::new(keyboard::print_keypresses())); + + println!("[ ] Starting async executor"); + executor.run(); xe_os::hlt_loop(); } @@ -44,3 +48,18 @@ fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! { xe_os::test_panic_handler(info); } + +async fn async_number() -> u32 { + 42 +} + +async fn example_task() { + let number = async_number().await; + println!("async number: {}", number); +} + +async fn h_task() { + println!("[ ] Running WASM:"); + wasm::run().await; + println!(" success"); +} diff --git a/src/memory.rs b/src/memory.rs index 11c5044..ddf668d 100644 --- a/src/memory.rs +++ b/src/memory.rs @@ -1,7 +1,7 @@ use bootloader::bootinfo::{MemoryMap, MemoryRegionType}; use x86_64::{ structures::paging::{ - FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, + FrameAllocator, Mapper, OffsetPageTable, Page, PageTable, PhysFrame, Size4KiB, UnusedPhysFrame, }, PhysAddr, VirtAddr, }; @@ -35,30 +35,6 @@ unsafe fn active_level_4_table(physical_memory_offset: VirtAddr) -> &'static mut &mut *page_table_ptr // unsafe } -/// Creates an example mapping for the given page to frame `0xb8000`. -pub fn create_example_mapping( - page: Page, - mapper: &mut OffsetPageTable, - frame_allocator: &mut impl FrameAllocator, -) { - use x86_64::structures::paging::PageTableFlags as Flags; - - let frame = PhysFrame::containing_address(PhysAddr::new(0xb8000)); - let flags = Flags::PRESENT | Flags::WRITABLE; - - let map_to_result = unsafe { mapper.map_to(page, frame, flags, frame_allocator) }; - map_to_result.expect("map_to failed").flush(); -} - -/// A FrameAllocator that always returns `None`. -pub struct EmptyFrameAllocator; - -unsafe impl FrameAllocator for EmptyFrameAllocator { - fn allocate_frame(&mut self) -> Option { - None - } -} - /// A FrameAllocator that returns usable frames from the bootloader's memory map. pub struct BootInfoFrameAllocator { memory_map: &'static MemoryMap, @@ -77,25 +53,32 @@ impl BootInfoFrameAllocator { next: 0, } } +} +impl BootInfoFrameAllocator { /// Returns an iterator over the usable frames specified in the memory map. - fn usable_frames(&self) -> impl Iterator { + fn usable_frames(&self) -> impl Iterator { // get usable regions from memory map let regions = self.memory_map.iter(); - let usable_regions = regions.filter(|r| r.region_type == MemoryRegionType::Usable); + let usable_regions = regions + .filter(|r| r.region_type == MemoryRegionType::Usable); // map each region to its address range - let addr_ranges = usable_regions.map(|r| r.range.start_addr()..r.range.end_addr()); + let addr_ranges = usable_regions + .map(|r| r.range.start_addr()..r.range.end_addr()); // transform to an iterator of frame start addresses let frame_addresses = addr_ranges.flat_map(|r| r.step_by(4096)); // create `PhysFrame` types from the start addresses - frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))) + let frames = frame_addresses.map(|addr| PhysFrame::containing_address(PhysAddr::new(addr))); + // we know that the frames are really unused + frames.map(|f| unsafe { UnusedPhysFrame::new(f) }) } } unsafe impl FrameAllocator for BootInfoFrameAllocator { - fn allocate_frame(&mut self) -> Option { + fn allocate_frame(&mut self) -> Option { let frame = self.usable_frames().nth(self.next); self.next += 1; frame } } + diff --git a/src/task/executor.rs b/src/task/executor.rs new file mode 100644 index 0000000..c20beba --- /dev/null +++ b/src/task/executor.rs @@ -0,0 +1,108 @@ +use super::{Task, TaskId}; +use alloc::{collections::{BTreeMap, VecDeque}, sync::Arc, task::Wake}; +use core::task::{Context, Poll, Waker}; +use crossbeam_queue::ArrayQueue; + +pub struct Executor { + task_queue: VecDeque, + waiting_tasks: BTreeMap, + wake_queue: Arc>, + waker_cache: BTreeMap, +} + +impl Executor { + pub fn new() -> Self { + Executor { + task_queue: VecDeque::new(), + waiting_tasks: BTreeMap::new(), + wake_queue: Arc::new(ArrayQueue::new(100)), + waker_cache: BTreeMap::new(), + } + } + + pub fn spawn(&mut self, task: Task) { + self.task_queue.push_back(task) + } + + fn run_ready_tasks(&mut self) { + while let Some(mut task) = self.task_queue.pop_front() { + let task_id = task.id(); + if !self.waker_cache.contains_key(&task_id) { + self.waker_cache.insert(task_id, self.create_waker(task_id)); + } + let waker = self.waker_cache.get(&task_id).expect("should exist"); + let mut context = Context::from_waker(waker); + match task.poll(&mut context) { + Poll::Ready(()) => { + // task done -> remove cached waker + self.waker_cache.remove(&task_id); + } + Poll::Pending => { + if self.waiting_tasks.insert(task_id, task).is_some() { + panic!("task with same ID already in waiting_tasks"); + } + }, + } + } + } + + fn create_waker(&self, task_id: TaskId) -> Waker { + Waker::from(Arc::new(TaskWaker { + task_id, + wake_queue: self.wake_queue.clone(), + })) + } + + fn wake_tasks(&mut self) { + while let Ok(task_id) = self.wake_queue.pop() { + if let Some(task) = self.waiting_tasks.remove(&task_id) { + self.task_queue.push_back(task); + } + } + } + + pub fn run(&mut self) -> ! { + loop { + self.wake_tasks(); + self.run_ready_tasks(); + self.sleep_if_idle(); + } + } + + fn sleep_if_idle(&self) { + use x86_64::instructions::interrupts::{self, enable_interrupts_and_hlt}; + + // fast path + if !self.wake_queue.is_empty() { + return; + } + + interrupts::disable(); + if self.wake_queue.is_empty() { + enable_interrupts_and_hlt(); + } else { + interrupts::enable(); + } + } +} + +struct TaskWaker { + task_id: TaskId, + wake_queue: Arc>, +} + +impl TaskWaker { + fn wake_task(&self) { + self.wake_queue.push(self.task_id).expect("wake_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/src/task/keyboard.rs b/src/task/keyboard.rs new file mode 100644 index 0000000..343ddc9 --- /dev/null +++ b/src/task/keyboard.rs @@ -0,0 +1,78 @@ +use crate::{print, println}; +use conquer_once::spin::OnceCell; +use core::{pin::Pin, task::{Poll, Context}}; +use crossbeam_queue::ArrayQueue; +use futures_util::{stream::{Stream, StreamExt}, task::AtomicWaker}; +use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1}; + +static SCANCODE_QUEUE: OnceCell> = OnceCell::uninit(); + +/// Called by the keyboard interrupt handler +/// +/// Must not block or allocate. +pub(crate) fn add_scancode(scancode: u8) { + if let Ok(queue) = SCANCODE_QUEUE.try_get() { + if let Err(_) = queue.push(scancode) { + println!("WARNING: scancode queue full; dropping keyboard input"); + } else { + WAKER.wake(); // new + } + } else { + println!("WARNING: scancode queue uninitialized"); + } +} + +pub struct ScancodeStream { + _private: (), +} + +impl ScancodeStream { + pub fn new() -> Self { + SCANCODE_QUEUE.try_init_once(|| ArrayQueue::new(100)) + .expect("ScancodeStream::new should only be called once"); + ScancodeStream { _private: () } + } +} + +impl Stream for ScancodeStream { + type Item = u8; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll> { + let queue = SCANCODE_QUEUE + .try_get() + .expect("scancode queue not initialized"); + + // fast path + if let Ok(scancode) = queue.pop() { + return Poll::Ready(Some(scancode)); + } + + WAKER.register(&cx.waker()); + match queue.pop() { + Ok(scancode) => { + WAKER.take(); + Poll::Ready(Some(scancode)) + } + Err(crossbeam_queue::PopError) => Poll::Pending, + } + } +} + +static WAKER: AtomicWaker = AtomicWaker::new(); + +pub async fn print_keypresses() { + let mut scancodes = ScancodeStream::new(); + let mut keyboard = Keyboard::new(layouts::Us104Key, ScancodeSet1, + HandleControl::Ignore); + + while let Some(scancode) = scancodes.next().await { + if let Ok(Some(key_event)) = keyboard.add_byte(scancode) { + if let Some(key) = keyboard.process_keyevent(key_event) { + match key { + DecodedKey::Unicode(character) => print!("{}", character), + DecodedKey::RawKey(key) => print!("{:?}", key), + } + } + } + } +} diff --git a/src/task/mod.rs b/src/task/mod.rs new file mode 100644 index 0000000..aee73d9 --- /dev/null +++ b/src/task/mod.rs @@ -0,0 +1,32 @@ +use core::{future::Future, pin::Pin, task::{Context, Poll}}; +use alloc::boxed::Box; + +pub mod executor; +pub mod keyboard; +pub mod simple_executor; + +pub struct Task { + future: Pin>>, +} + +impl Task { + pub fn new(future: impl Future + 'static) -> Task { + Task{ + future: Box::pin(future), + } + } + + fn poll (&mut self, context: &mut Context) -> Poll<()> { + self.future.as_mut().poll(context) + } + + fn id(&self) -> TaskId { + use core::ops::Deref; + + let addr = Pin::deref(&self.future) as *const _ as *const () as usize; + TaskId(addr) + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +struct TaskId(usize); diff --git a/src/task/simple_executor.rs b/src/task/simple_executor.rs new file mode 100644 index 0000000..2f257ad --- /dev/null +++ b/src/task/simple_executor.rs @@ -0,0 +1,44 @@ +use super::Task; +use alloc::collections::VecDeque; +use core::task::{Waker, RawWaker, RawWakerVTable, Context, Poll}; + +fn dummy_raw_waker() -> RawWaker { + fn no_op(_: *const ()) {} + fn clone(_: *const ()) -> RawWaker { + dummy_raw_waker() + } + + let vtable = &RawWakerVTable::new(clone, no_op, no_op, no_op); + RawWaker::new(0 as *const (), vtable) +} + +fn dummy_waker() -> Waker { + unsafe { Waker::from_raw(dummy_raw_waker()) } +} + +pub struct SimpleExecutor { + task_queue: VecDeque, +} + +impl SimpleExecutor { + pub fn new() -> SimpleExecutor { + SimpleExecutor { + task_queue: VecDeque::new(), + } + } + + pub fn spawn(&mut self, task: Task) { + self.task_queue.push_back(task) + } + + pub fn run(&mut self) { + while let Some(mut task) = self.task_queue.pop_front() { + let waker = dummy_waker(); + let mut context = Context::from_waker(&waker); + match task.poll(&mut context) { + Poll::Ready(()) => {} // task done + Poll::Pending => self.task_queue.push_back(task), + } + } + } +} diff --git a/src/wasm/mod.rs b/src/wasm/mod.rs index 193598b..9d405bf 100644 --- a/src/wasm/mod.rs +++ b/src/wasm/mod.rs @@ -9,12 +9,12 @@ use crate::{serial_print, serial_println}; mod hack; -pub fn run() { +pub async fn run() { use alloc::vec::Vec; let bytes = include_bytes!("../../data/h.wasm"); let b: Vec = bytes.iter().cloned().collect(); - println!("[ ] loaded wasm into a Vec"); + println!(" loaded wasm into a Vec"); let module = wasmi::Module::from_buffer(&b).unwrap(); let mut imports = ImportsBuilder::new(); @@ -24,7 +24,7 @@ pub fn run() { .expect("failed to load wasm module") .assert_no_start(); - println!("[ ] invoking export"); + println!(" invoking export"); let _ = instance.invoke_export("h", &[], &mut H); }