Compare commits

...

4 Commits

Author SHA1 Message Date
Philipp Oppermann
ca8cd46863 Update 2020-03-22 11:58:16 +01:00
Philipp Oppermann
816f8746fb Implement a ScancodeStream type 2020-03-20 14:14:45 +01:00
Philipp Oppermann
255982a8b7 Implement scancode queue 2020-03-20 13:03:41 +01:00
Philipp Oppermann
f885f17b70 Implement a simple poll-loop executor 2020-03-19 16:46:37 +01:00
7 changed files with 226 additions and 25 deletions

79
Cargo.lock generated
View File

@@ -1,5 +1,11 @@
# This file is automatically @generated by Cargo. # This file is automatically @generated by Cargo.
# It is not intended for manual editing. # It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
[[package]] [[package]]
name = "bit_field" name = "bit_field"
version = "0.9.0" version = "0.9.0"
@@ -17,6 +23,9 @@ name = "blog_os"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bootloader", "bootloader",
"conquer-once",
"crossbeam-queue",
"futures-util",
"lazy_static", "lazy_static",
"linked_list_allocator", "linked_list_allocator",
"pc-keyboard", "pc-keyboard",
@@ -30,8 +39,27 @@ dependencies = [
[[package]] [[package]]
name = "bootloader" name = "bootloader"
version = "0.8.8" version = "0.8.8"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3ed4f735c4e455ba86a3d2939b1c0729414153642106c9d035693355630a42c" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "conquer-once"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f7644600a548ecad74e4a918392af1798f7dd045be610be3203b9e129b4f98f"
dependencies = [
"conquer-util",
]
[[package]]
name = "conquer-util"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "654fb2472cc369d311c547103a1fa81d467bef370ae7a0680f65939895b1182a"
[[package]] [[package]]
name = "cpuio" name = "cpuio"
@@ -39,6 +67,49 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22b8e308ccfc5acf3b82f79c0eac444cf6114cb2ac67a230ca6c177210068daa" checksum = "22b8e308ccfc5acf3b82f79c0eac444cf6114cb2ac67a230ca6c177210068daa"
[[package]]
name = "crossbeam-queue"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
dependencies = [
"autocfg",
"cfg-if",
]
[[package]]
name = "futures-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f25592f769825e89b92358db00d26f965761e094951ac44d3663ef25b7ac464a"
[[package]]
name = "futures-task"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0a34e53cf6cdcd0178aa573aed466b646eb3db769570841fda0c7ede375a27"
[[package]]
name = "futures-util"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22766cf25d64306bedf0384da004d05c9974ab104fcc4528f1236181c18004c5"
dependencies = [
"futures-core",
"futures-task",
"pin-utils",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@@ -81,6 +152,12 @@ dependencies = [
"cpuio", "cpuio",
] ]
[[package]]
name = "pin-utils"
version = "0.1.0-alpha.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
version = "1.1.0" version = "1.1.0"

View File

@@ -26,6 +26,19 @@ linked_list_allocator = "0.8.0"
version = "1.0" version = "1.0"
features = ["spin_no_std"] features = ["spin_no_std"]
[dependencies.crossbeam-queue]
version = "0.2.1"
default-features = false
features = ["alloc"]
[dependencies.conquer-once]
version = "0.2.0"
default-features = false
[dependencies.futures-util]
version = "0.3.4"
default-features = false
features = ["alloc", "async-await"]
[package.metadata.bootimage] [package.metadata.bootimage]
test-args = [ test-args = [

View File

@@ -6,6 +6,8 @@
#![feature(const_fn)] #![feature(const_fn)]
#![feature(alloc_layout_extra)] #![feature(alloc_layout_extra)]
#![feature(const_in_array_repeat_expressions)] #![feature(const_in_array_repeat_expressions)]
#![feature(wake_trait)]
#![feature(async_closure)]
#![test_runner(crate::test_runner)] #![test_runner(crate::test_runner)]
#![reexport_test_harness_main = "test_main"] #![reexport_test_harness_main = "test_main"]
@@ -18,6 +20,7 @@ pub mod gdt;
pub mod interrupts; pub mod interrupts;
pub mod memory; pub mod memory;
pub mod serial; pub mod serial;
pub mod task;
pub mod vga_buffer; pub mod vga_buffer;
pub fn init() { pub fn init() {

View File

@@ -6,7 +6,6 @@
extern crate alloc; extern crate alloc;
use alloc::{boxed::Box, rc::Rc, vec, vec::Vec};
use blog_os::println; use blog_os::println;
use bootloader::{entry_point, BootInfo}; use bootloader::{entry_point, BootInfo};
use core::panic::PanicInfo; use core::panic::PanicInfo;
@@ -16,6 +15,7 @@ entry_point!(kernel_main);
fn kernel_main(boot_info: &'static BootInfo) -> ! { fn kernel_main(boot_info: &'static BootInfo) -> ! {
use blog_os::allocator; use blog_os::allocator;
use blog_os::memory::{self, BootInfoFrameAllocator}; use blog_os::memory::{self, BootInfoFrameAllocator};
use blog_os::task::{simple_executor::SimpleExecutor, Task, keyboard};
use x86_64::VirtAddr; use x86_64::VirtAddr;
println!("Hello World{}", "!"); println!("Hello World{}", "!");
@@ -27,29 +27,10 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed"); allocator::init_heap(&mut mapper, &mut frame_allocator).expect("heap initialization failed");
// allocate a number on the heap let mut executor = SimpleExecutor::new();
let heap_value = Box::new(41); executor.spawn(Task::new(example_task()));
println!("heap_value at {:p}", heap_value); executor.spawn(Task::new(keyboard::print_keypresses()));
executor.run();
// create a dynamically sized vector
let mut vec = Vec::new();
for i in 0..500 {
vec.push(i);
}
println!("vec at {:p}", vec.as_slice());
// create a reference counted vector -> will be freed when count reaches 0
let reference_counted = Rc::new(vec![1, 2, 3]);
let cloned_reference = reference_counted.clone();
println!(
"current reference count is {}",
Rc::strong_count(&cloned_reference)
);
core::mem::drop(reference_counted);
println!(
"reference count is {} now",
Rc::strong_count(&cloned_reference)
);
#[cfg(test)] #[cfg(test)]
test_main(); test_main();
@@ -58,6 +39,15 @@ fn kernel_main(boot_info: &'static BootInfo) -> ! {
blog_os::hlt_loop(); blog_os::hlt_loop();
} }
async fn async_number() -> u32 {
42
}
async fn example_task() {
let number = async_number().await;
println!("async number: {}", number);
}
/// This function is called on panic. /// This function is called on panic.
#[cfg(not(test))] #[cfg(not(test))]
#[panic_handler] #[panic_handler]

52
src/task/keyboard.rs Normal file
View File

@@ -0,0 +1,52 @@
use conquer_once::spin::OnceCell;
use crossbeam_queue::ArrayQueue;
use futures_util::stream::{Stream, StreamExt};
use core::{pin::Pin, task::{Context, Poll}};
use pc_keyboard::{layouts, DecodedKey, HandleControl, Keyboard, ScancodeSet1};
use crate::print;
static SCANCODE_QUEUE: OnceCell<ArrayQueue<u8>> = OnceCell::uninit();
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>, context: &mut Context) -> Poll<Option<u8>> {
let queue = SCANCODE_QUEUE
.try_get()
.expect("scancode queue not initialized");
match queue.pop() {
Ok(scancode) => Poll::Ready(Some(scancode)),
Err(crossbeam_queue::PopError) => Poll::Pending,
}
}
}
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),
}
}
}
}
}

22
src/task/mod.rs Normal file
View File

@@ -0,0 +1,22 @@
use alloc::boxed::Box;
use core::task::{Context, Poll};
use core::{future::Future, pin::Pin};
pub mod keyboard;
pub mod simple_executor;
pub struct Task {
future: Pin<Box<dyn Future<Output = ()>>>,
}
impl Task {
pub fn new(future: impl Future<Output = ()> + 'static) -> Task {
Task {
future: Box::pin(future),
}
}
fn poll(&mut self, context: &mut Context) -> Poll<()> {
self.future.as_mut().poll(context)
}
}

View File

@@ -0,0 +1,44 @@
use super::Task;
use alloc::{collections::VecDeque, sync::Arc, task::Wake};
use core::task::{Context, Poll, Waker};
pub struct SimpleExecutor {
task_queue: VecDeque<Task>,
}
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 = DummyWaker.to_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),
}
}
}
}
struct DummyWaker;
impl Wake for DummyWaker {
fn wake(self: Arc<Self>) {
// do nothing
}
}
impl DummyWaker {
fn to_waker(self) -> Waker {
Waker::from(Arc::new(self))
}
}