diff --git a/Cargo.lock b/Cargo.lock index 870c75e..7db7b52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,46 +2,154 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" + +[[package]] +name = "anstyle-parse" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" -[[package]] -name = "bitvec" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" -dependencies = [ - "funty", - "radium", - "tap", - "wyz", -] - [[package]] name = "cfg-if" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" +[[package]] +name = "colorchoice" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" + [[package]] name = "curio" version = "0.1.0" dependencies = [ - "bitvec", + "env_logger", "io-uring", "libc", + "log", "send_wrapper", "slab", ] [[package]] -name = "funty" +name = "defmt" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2953bfe4f93bbd20cc71198842756f77d161884c99ebbabc41d80231ded88d1" +dependencies = [ + "bitflags 1.3.2", + "defmt-macros", +] + +[[package]] +name = "defmt-macros" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bad9c72e7ca2137e0dc3813245a0d282fd6daad32fd800af018306a9169b5fe8" +dependencies = [ + "defmt-parser", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "defmt-parser" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10d60334b3b2e7c9d91ef8150abfb6fa4c1c39ebbcf4a81c2e346aad939fee3e" +dependencies = [ + "thiserror", +] + +[[package]] +name = "env_filter" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +checksum = "900d271a03799a1ee8d1ca9b19893b48ca674a9284fefcfb85f05e74ed314217" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de671bd27a75a797dc9ae289ba1e77276e75e2026408aab65185384e2d5cd3f6" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "jiff", + "log", +] [[package]] name = "io-uring" @@ -49,11 +157,54 @@ version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed3bd0ecfbb87805f538bb7b32e5239ca0763890c623e349860ecba69469f2bb" dependencies = [ - "bitflags", + "bitflags 2.13.2", "cfg-if", "libc", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" + +[[package]] +name = "jiff" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ab1baf72f08796de0260609515130699b890ac25f30e610ad894bc5856cafdb" +dependencies = [ + "defmt", + "jiff-core", + "jiff-static", + "log", + "portable-atomic", + "portable-atomic-util", + "serde_core", +] + +[[package]] +name = "jiff-core" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e52fe76043ccecc9005d2305ebaadf7d7fc0cc89ca6baa10a94d6bc68c7128c" +dependencies = [ + "defmt", + "log", +] + +[[package]] +name = "jiff-static" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "378268a1116ad67ae6228701118ac9f491d78fda38a40a1f1a9e1348de6f7212" +dependencies = [ + "jiff-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "libc" version = "0.2.189" @@ -61,10 +212,84 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] -name = "radium" -version = "0.7.0" +name = "log" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "once_cell_polyfill" +version = "1.70.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" + +[[package]] +name = "portable-atomic" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" + +[[package]] +name = "portable-atomic-util" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10ab3eb7f3becc3a1cbc4f2c6f20267996cfc1a6467a873763411b136a122715" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "send_wrapper" @@ -72,6 +297,26 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + [[package]] name = "slab" version = "0.4.12" @@ -79,16 +324,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] -name = "tap" -version = "1.0.1" +name = "syn" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] [[package]] -name = "wyz" -version = "0.5.1" +name = "syn" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ - "tap", + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", +] + +[[package]] +name = "unicode-ident" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] diff --git a/Cargo.toml b/Cargo.toml index e57a740..a81d56e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,8 +4,9 @@ version = "0.1.0" edition = "2024" [dependencies] -bitvec = "1.1.1" +env_logger = "0.11.11" io-uring = "0.7.15" libc = "0.2.189" +log = "0.4.34" send_wrapper = "0.6.0" slab = "0.4.12" diff --git a/src/lib.rs b/src/lib.rs index 6c3b8c7..0f9ac31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,16 @@ #![feature(local_waker)] #![feature(waker_fn)] -#![feature(context_ext)] use std::{ - cell::RefCell, io::ErrorKind, pin::{Pin, pin}, rc::{Rc, Weak}, task::{Context, ContextBuilder, Poll, Waker, local_waker_fn, waker_fn}, time::Instant, + cell::RefCell, pin::Pin, rc::{Rc, Weak}, task::{ContextBuilder, Poll, local_waker_fn, waker_fn}, thread::sleep, time::Instant, }; -use io_uring::{IoUring, types::{SubmitArgs, Timespec}}; -use libc::ETIME; +use io_uring::{ + IoUring, + types::{SubmitArgs, Timespec}, +}; +use libc::{ETIME}; +use log::trace; use send_wrapper::SendWrapper; use slab::Slab; @@ -29,7 +32,6 @@ pub struct RuntimeInner { pub struct Runtime(Rc>); struct RuntimeWeak(Weak>); - thread_local! { static RT: RefCell> = RefCell::new(None); } @@ -64,7 +66,10 @@ impl Runtime { pub fn spawn(&self, fut: Pin>>) { let mut inner = self.0.borrow_mut(); - let task_id = inner.tasks.insert(Task { fut: Some(fut), ready: true }); + let task_id = inner.tasks.insert(Task { + fut: Some(fut), + ready: true, + }); inner.runqueue.push(task_id); } @@ -74,26 +79,42 @@ impl Runtime { pub fn run(&mut self) { RT.set(Some(Runtime(Rc::clone(&self.0)))); - while !self.0.borrow().tasks.is_empty() { + let mut lock = self.0.borrow_mut(); + while !lock.tasks.is_empty() { // Run until no ready tasks, no timers, no future CQEs + trace!("Polling tasks"); loop { - let task_id = { - let mut lock = self.0.borrow_mut(); - let Some(task_id) = lock.runqueue.pop() else { - break; - }; - lock.tasks[task_id].ready = false; - task_id + let Some(task_id) = lock.runqueue.pop() else { + break; }; + trace!("Polling task {}", task_id); + lock.tasks[task_id].ready = false; let waker = { let inner = SendWrapper::new(self.downgrade()); waker_fn(move || { if let Some(inner) = inner.0.upgrade() { + trace!("Waking {}", task_id); let mut lock = inner.borrow_mut(); let ready = &mut lock.tasks[task_id].ready; if !*ready { + trace!("Enqueueing {}", task_id); + *ready = true; + lock.runqueue.push(task_id); + } + } + }) + }; + let local_waker = { + let inner = SendWrapper::new(self.downgrade()); + local_waker_fn(move || { + if let Some(inner) = inner.0.upgrade() { + trace!("Local waking {}", task_id); + let mut lock = inner.borrow_mut(); + let ready = &mut lock.tasks[task_id].ready; + if !*ready { + trace!("Local enqueueing {}", task_id); *ready = true; lock.runqueue.push(task_id); } @@ -101,45 +122,63 @@ impl Runtime { }) }; let mut cx = ContextBuilder::from_waker(&waker) + .local_waker(&local_waker) .build(); - let mut task = self.0.borrow_mut().tasks[task_id].fut.take().unwrap(); - match task.as_mut().poll(&mut cx) { + let mut task = lock.tasks[task_id].fut.take().unwrap(); + drop(lock); + let outcome = task.as_mut().poll(&mut cx); + lock = self.0.borrow_mut(); + match outcome { Poll::Ready(()) => { - self.0.borrow_mut().tasks.remove(task_id); + lock.tasks.remove(task_id); } Poll::Pending => { - self.0.borrow_mut().tasks[task_id].fut = Some(task); + lock.tasks[task_id].fut = Some(task); } } } let now = Instant::now(); + trace!("Polling timers"); let wait = loop { - let mut lock = self.0.borrow_mut(); match lock.timer.poll(now) { - timer::Status::Empty => break None, - timer::Status::Pending(deadline) => break Some(Timespec::from(deadline - now)), + timer::Status::Empty => { + trace!("No timers expired"); + break None; + } + timer::Status::Pending(deadline) => { + trace!("Next timer expiring in {:?}", deadline - now); + break Some(Timespec::from(deadline - now)); + } timer::Status::Expired(waker) => { + trace!("Timer expired, waking"); drop(lock); waker.wake(); + lock = self.0.borrow_mut(); } } }; let mut args = SubmitArgs::new(); - if let Some(wait) = &wait { - args = args.timespec(&wait); - } - match self.0.borrow_mut().ring.submitter().submit_with_args(1, &args) { + trace!("Entering ring"); + let want = match &wait { + Some(wait) => { + args = args.timespec(wait); + 1 + } + None => 0, + }; + match lock.ring.submitter().submit_with_args(want, &args) { Ok(n) => { debug_assert_eq!(n, 0); } - Err(err) if err.raw_os_error() == Some(ETIME) => {}, + Err(err) if err.raw_os_error() == Some(ETIME) && wait.is_some() => {} e => { e.expect("failed to enter ring"); - }, + } } } + trace!("Exiting"); } } @@ -147,12 +186,13 @@ impl Runtime { mod tests { use std::time::Duration; -use crate::timer::delay; + use crate::timer::delay; -use super::*; + use super::*; #[test] fn it_works() { + env_logger::init(); let mut runtime = Runtime::new(); runtime.spawn(Box::pin(async { println!("1"); diff --git a/src/timer.rs b/src/timer.rs index fb17107..6750a91 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -1,4 +1,13 @@ -use std::{borrow::BorrowMut as _, cell::RefCell, cmp::Reverse, collections::BinaryHeap, pin::Pin, rc::{Rc, Weak}, task::{Context, LocalWaker, Poll, Waker}, time::{Duration, Instant}}; +use std::{ + borrow::BorrowMut as _, + cell::RefCell, + cmp::Reverse, + collections::BinaryHeap, + pin::Pin, + rc::{Rc, Weak}, + task::{Context, LocalWaker, Poll}, + time::{Duration, Instant}, +}; use slab::Slab; @@ -95,7 +104,9 @@ impl Drop for Timer { pub fn delay_until(deadline: Instant) -> Timer { Timer { slot: RT.with_borrow(|rt| { - let rt = rt.as_ref().expect("called from outside curio runtime thread"); + let rt = rt + .as_ref() + .expect("called from outside curio runtime thread"); let mut lock = rt.0.as_ref().borrow_mut(); lock.timer.insert(deadline) }),