summaryrefslogtreecommitdiff
path: root/rust/pin-init/examples/mutex.rs
diff options
context:
space:
mode:
authorMiguel Ojeda <ojeda@kernel.org>2025-07-13 23:05:14 +0200
committerMiguel Ojeda <ojeda@kernel.org>2025-07-13 23:05:14 +0200
commite8fa0481ea15ba1d40a836fa5dbfc1f49680fba8 (patch)
treefe27d83903fb413e95ce0846aaab87bf44037cee /rust/pin-init/examples/mutex.rs
parent2009a2d5696944d85c34d75e691a6f3884e787c0 (diff)
parentfc3870dc5cadb701b4122e4a8daa85f9fa2f57b9 (diff)
Merge tag 'pin-init-v6.17' of https://github.com/Rust-for-Linux/linux into rust-next
Pull pin-init updates from Benno Lossin: "Added: - 'impl<T, E> [Pin]Init<T, E> for Result<T, E>', so results are now (pin-)initializers. - 'Zeroable::init_zeroed()' delegating to 'init_zeroed()'. - New 'zeroed()', a safe version of 'mem::zeroed()' and also provide it via 'Zeroable::zeroed()'. - Implement 'Zeroable' for 'Option<&T>' and 'Option<&mut T>'. - Implement 'Zeroable' for 'Option<[unsafe] [extern "abi"] fn(...args...) -> ret>' for '"Rust"' and '"C"' ABIs and up to 20 arguments. Changed: - Blanket impls of 'Init' and 'PinInit' from 'impl<T, E> [Pin]Init<T, E> for T' to 'impl<T> [Pin]Init<T> for T'. - Renamed 'zeroed()' to 'init_zeroed()'. Upstream dev news: - More CI improvements to deny warnings, use '--all-targets'. Also check the synchronization status of the two '-next' branches in upstream and the kernel." Acked-by: Andreas Hindborg <a.hindborg@kernel.org> * tag 'pin-init-v6.17' of https://github.com/Rust-for-Linux/linux: rust: pin-init: examples, tests: use `ignore` instead of conditionally compiling tests rust: init: remove doctest's `Error::from_errno` workaround rust: init: re-enable doctests rust: pin-init: implement `ZeroableOption` for function pointers with up to 20 arguments rust: pin-init: change `impl Zeroable for Option<NonNull<T>>` to `ZeroableOption for NonNull<T>` rust: pin-init: implement `ZeroableOption` for `&T` and `&mut T` rust: pin-init: add `zeroed()` & `Zeroable::zeroed()` functions rust: pin-init: add `Zeroable::init_zeroed` rust: pin-init: rename `zeroed` to `init_zeroed` rust: pin-init: feature-gate the `stack_init_reuse` test on the `std` feature rust: pin-init: examples: pthread_mutex: disable the main test for miri rust: pin-init: examples, tests: add conditional compilation in order to compile under any feature combination rust: pin-init: change blanket impls for `[Pin]Init` and add one for `Result<T, E>` rust: pin-init: improve safety documentation for `impl<T> [Pin]Init<T> for T`
Diffstat (limited to 'rust/pin-init/examples/mutex.rs')
-rw-r--r--rust/pin-init/examples/mutex.rs97
1 files changed, 56 insertions, 41 deletions
diff --git a/rust/pin-init/examples/mutex.rs b/rust/pin-init/examples/mutex.rs
index 3e3630780c96..9f295226cd64 100644
--- a/rust/pin-init/examples/mutex.rs
+++ b/rust/pin-init/examples/mutex.rs
@@ -12,14 +12,15 @@ use core::{
pin::Pin,
sync::atomic::{AtomicBool, Ordering},
};
+#[cfg(feature = "std")]
use std::{
sync::Arc,
- thread::{self, park, sleep, Builder, Thread},
+ thread::{self, sleep, Builder, Thread},
time::Duration,
};
use pin_init::*;
-#[expect(unused_attributes)]
+#[allow(unused_attributes)]
#[path = "./linked_list.rs"]
pub mod linked_list;
use linked_list::*;
@@ -36,6 +37,7 @@ impl SpinLock {
.compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed)
.is_err()
{
+ #[cfg(feature = "std")]
while self.inner.load(Ordering::Relaxed) {
thread::yield_now();
}
@@ -94,7 +96,8 @@ impl<T> CMutex<T> {
// println!("wait list length: {}", self.wait_list.size());
while self.locked.get() {
drop(sguard);
- park();
+ #[cfg(feature = "std")]
+ thread::park();
sguard = self.spin_lock.acquire();
}
// This does have an effect, as the ListHead inside wait_entry implements Drop!
@@ -131,8 +134,11 @@ impl<T> Drop for CMutexGuard<'_, T> {
let sguard = self.mtx.spin_lock.acquire();
self.mtx.locked.set(false);
if let Some(list_field) = self.mtx.wait_list.next() {
- let wait_entry = list_field.as_ptr().cast::<WaitEntry>();
- unsafe { (*wait_entry).thread.unpark() };
+ let _wait_entry = list_field.as_ptr().cast::<WaitEntry>();
+ #[cfg(feature = "std")]
+ unsafe {
+ (*_wait_entry).thread.unpark()
+ };
}
drop(sguard);
}
@@ -159,52 +165,61 @@ impl<T> DerefMut for CMutexGuard<'_, T> {
struct WaitEntry {
#[pin]
wait_list: ListHead,
+ #[cfg(feature = "std")]
thread: Thread,
}
impl WaitEntry {
#[inline]
fn insert_new(list: &ListHead) -> impl PinInit<Self> + '_ {
- pin_init!(Self {
- thread: thread::current(),
- wait_list <- ListHead::insert_prev(list),
- })
+ #[cfg(feature = "std")]
+ {
+ pin_init!(Self {
+ thread: thread::current(),
+ wait_list <- ListHead::insert_prev(list),
+ })
+ }
+ #[cfg(not(feature = "std"))]
+ {
+ pin_init!(Self {
+ wait_list <- ListHead::insert_prev(list),
+ })
+ }
}
}
-#[cfg(not(any(feature = "std", feature = "alloc")))]
-fn main() {}
-
-#[allow(dead_code)]
#[cfg_attr(test, test)]
-#[cfg(any(feature = "std", feature = "alloc"))]
+#[allow(dead_code)]
fn main() {
- let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap();
- let mut handles = vec![];
- let thread_count = 20;
- let workload = if cfg!(miri) { 100 } else { 1_000 };
- for i in 0..thread_count {
- let mtx = mtx.clone();
- handles.push(
- Builder::new()
- .name(format!("worker #{i}"))
- .spawn(move || {
- for _ in 0..workload {
- *mtx.lock() += 1;
- }
- println!("{i} halfway");
- sleep(Duration::from_millis((i as u64) * 10));
- for _ in 0..workload {
- *mtx.lock() += 1;
- }
- println!("{i} finished");
- })
- .expect("should not fail"),
- );
- }
- for h in handles {
- h.join().expect("thread panicked");
+ #[cfg(feature = "std")]
+ {
+ let mtx: Pin<Arc<CMutex<usize>>> = Arc::pin_init(CMutex::new(0)).unwrap();
+ let mut handles = vec![];
+ let thread_count = 20;
+ let workload = if cfg!(miri) { 100 } else { 1_000 };
+ for i in 0..thread_count {
+ let mtx = mtx.clone();
+ handles.push(
+ Builder::new()
+ .name(format!("worker #{i}"))
+ .spawn(move || {
+ for _ in 0..workload {
+ *mtx.lock() += 1;
+ }
+ println!("{i} halfway");
+ sleep(Duration::from_millis((i as u64) * 10));
+ for _ in 0..workload {
+ *mtx.lock() += 1;
+ }
+ println!("{i} finished");
+ })
+ .expect("should not fail"),
+ );
+ }
+ for h in handles {
+ h.join().expect("thread panicked");
+ }
+ println!("{:?}", &*mtx.lock());
+ assert_eq!(*mtx.lock(), workload * thread_count * 2);
}
- println!("{:?}", &*mtx.lock());
- assert_eq!(*mtx.lock(), workload * thread_count * 2);
}