Skip to content

Instantly share code, notes, and snippets.

@PeterCxy
Created May 23, 2025 21:21
Show Gist options
  • Save PeterCxy/b1307059fc0c06115e08f59f9664f407 to your computer and use it in GitHub Desktop.
Save PeterCxy/b1307059fc0c06115e08f59f9664f407 to your computer and use it in GitHub Desktop.
parking_lot RwLock lockup reproduction
use parking_lot::RwLock;
use std::ops::Deref;
use std::sync::Arc;
use std::time::Duration;
#[tokio::main(flavor = "multi_thread", worker_threads = 64)]
async fn main() {
let lock = Arc::new(RwLock::new(()));
//let mut addr = lock.deref() as *const RwLock<_> as *const usize;
//println!("lock addr is {addr:p}");
for _ in 0..1000 {
let lock = lock.clone();
tokio::task::spawn(async move { stress_lock(lock).await });
}
//let addr = addr as usize;
//std::thread::spawn(move || print_lock(addr));
tokio::time::sleep(Duration::from_secs(180)).await;
}
fn print_lock(addr: usize) {
let addr = addr as *const usize;
loop {
let val = unsafe { std::ptr::read_volatile(addr) };
println!("lock: {:x}", val);
std::thread::sleep(Duration::from_secs(1));
}
}
async fn stress_lock(lock: Arc<RwLock<()>>) {
loop {
let r: u32 = rand::random_range(..100);
if r == 0 {
#[cfg(feature = "write_timeout")]
write_timeout(&lock).await;
#[cfg(not(feature = "write_timeout"))]
write(&lock).await;
} else {
read(&lock).await
}
}
}
async fn read(lock: &Arc<RwLock<()>>) {
let guard = lock.read();
let r: u64 = rand::random_range(100..2000);
std::thread::sleep(Duration::from_micros(r));
drop(guard);
}
#[cfg(not(feature = "write_timeout"))]
async fn write(lock: &Arc<RwLock<()>>) {
let guard = lock.write();
let r: u64 = rand::random_range(100..1000);
std::thread::sleep(Duration::from_micros(r));
drop(guard);
}
#[cfg(feature = "write_timeout")]
async fn write_timeout(lock: &Arc<parking_lot::RwLock<()>>) {
let guard = loop {
if let Some(guard) = lock.try_write_for(Duration::from_micros(100)) {
break guard;
}
std::thread::sleep(Duration::from_micros(100));
};
let r: u64 = rand::random_range(100..1000);
std::thread::sleep(Duration::from_micros(r));
drop(guard);
}
use parking_lot::RwLock;
use std::ops::Deref;
use std::sync::Arc;
use std::time::Duration;
fn main() {
let lock = Arc::new(RwLock::new(()));
for _ in 0..64 {
let lock = lock.clone();
std::thread::spawn(move || stress_lock(lock));
}
//let addr = lock.deref() as *const RwLock<_> as *const usize as usize;
//let t = std::thread::spawn(move || print_lock(addr));
t.join().ok();
}
//fn print_lock(addr: usize) {
// let addr = addr as *const usize;
// loop {
// let val = unsafe { std::ptr::read_volatile(addr) };
// println!("lock: {:x}", val);
// std::thread::sleep(Duration::from_secs(1));
// }
//}
fn stress_lock(lock: Arc<RwLock<()>>) {
loop {
let r: u32 = rand::random_range(..100);
if r == 0 {
#[cfg(feature = "write_timeout")]
write_timeout(&lock);
#[cfg(not(feature = "write_timeout"))]
write(&lock);
} else {
read(&lock);
}
}
}
fn read(lock: &Arc<RwLock<()>>) {
let guard = lock.read();
let r: u64 = rand::random_range(100..2000);
std::thread::sleep(Duration::from_micros(r));
drop(guard);
}
#[cfg(not(feature = "write_timeout"))]
fn write(lock: &Arc<RwLock<()>>) {
let guard = lock.write();
let r: u64 = rand::random_range(100..1000);
std::thread::sleep(Duration::from_micros(r));
drop(guard);
}
#[cfg(feature = "write_timeout")]
fn write_timeout(lock: &Arc<parking_lot::RwLock<()>>) {
let guard = loop {
if let Some(guard) = lock.try_write_for(Duration::from_micros(100)) {
break guard;
}
std::thread::sleep(Duration::from_micros(100));
};
let r: u64 = rand::random_range(100..1000);
std::thread::sleep(Duration::from_micros(r));
drop(guard);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment