diff --git a/Cargo.lock b/Cargo.lock index acc0338..4322734 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,6 +8,7 @@ version = "0.1.0" dependencies = [ "bitflags", "linux-raw-sys", + "rand", "spin", ] @@ -17,14 +18,152 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + +[[package]] +name = "libc" +version = "0.2.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" + [[package]] name = "linux-raw-sys" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.103" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom", +] + [[package]] name = "spin" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" + +[[package]] +name = "syn" +version = "2.0.111" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "wasip2" +version = "1.0.1+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "zerocopy" +version = "0.8.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index 2282781..63c9534 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,6 @@ linux-raw-sys = { version = "0.11", default-features = false, features = [ "general", ] } spin = { version = "0.10", default-features = false, features = ["spin_mutex"] } + +[dev-dependencies] +rand = "0.9" \ No newline at end of file diff --git a/tests/tests.rs b/tests/tests.rs index 57b316a..32482e4 100644 --- a/tests/tests.rs +++ b/tests/tests.rs @@ -2,10 +2,14 @@ use std::{ sync::{ Arc, atomic::{AtomicUsize, Ordering}, + mpsc, }, task::{Context, Wake, Waker}, + thread, + time::Duration, }; +use rand::{Rng, rng}; use axpoll::PollSet; struct Counter(AtomicUsize); @@ -90,3 +94,52 @@ fn drop_wakes() { drop(ps); assert_eq!(counters.count(), 10); } + +#[test] +fn concurrent_registers() { + let ps = Arc::new(PollSet::new()); + let (tx, rx) = mpsc::channel(); + let threads_n = 50usize; + let per_thread = 200usize; + let total = threads_n * per_thread; + let mut handles = Vec::new(); + + let ps1 = ps.clone(); + let wake_handle = thread::spawn(move || { + for _ in 0..(threads_n * 10) { + ps1.as_ref().wake(); + let mut rng = rng(); + let s = rng.random_range(0..3); + thread::sleep(Duration::from_millis(s)); + } + }); + for _ in 0..threads_n { + let tx = tx.clone(); + let ps = ps.clone(); + let handle = thread::spawn(move || { + let mut rng = rng(); + for _ in 0..per_thread { + let counter = Counter::new(); + let w = Waker::from(counter.clone()); + let cx = Context::from_waker(&w); + if rng.random_bool(0.1) { + thread::sleep(Duration::from_micros(rng.random_range(0..500))); + } + ps.register(cx.waker()); + tx.send(counter).unwrap(); + } + }); + handles.push(handle); + } + + drop(tx); + for h in handles { + h.join().unwrap(); + } + wake_handle.join().unwrap(); + let counters: Vec<_> = rx.into_iter().collect(); + ps.wake(); + let woke: usize = counters.iter().map(|c| c.count()).sum(); + assert_eq!(counters.len(), total); + assert_eq!(woke, total); +}