Expand description
Minimal RCU (Read-Copy-Update) implementation
This crate provides a minimal Read-Copy-Update (RCU) synchronization mechanism specifically designed for OpenVMM use cases. RCU is a synchronization technique that allows multiple readers to access shared data concurrently with writers by ensuring that writers create new versions of data while readers continue using old versions.
This is similar to a reader-writer lock except that readers never wait: writers publish the new version of the data and then wait for all readers to finish using the old version before freeing it. This allows for very low overhead on the read side, as readers do not need to acquire locks.
§Usage
Basic usage with the global domain:
// Execute code in a read-side critical section
let result = minircu::global().run(|| {
// Access shared data safely here.
42
});
// Wait for all current readers to finish their critical sections.
// This is typically called by writers after updating data.
minircu::global().synchronize_blocking();
§Quiescing
To optimize synchronization, threads can explicitly quiesce when it is not expected to enter a critical section for a while. The RCU domain can skip issuing a memory barrier when all threads are quiesced.
use minircu::global;
// Mark the current thread as quiesced.
global().quiesce();
§Asynchronous Support
The crate provides async-compatible methods for quiescing and synchronization:
use minircu::global;
async fn example() {
// Quiesce whenever future returns Poll::Pending
global().quiesce_on_pending(async {
loop {
// Async code here.
global().run(|| {
// Access shared data safely here.
});
}
}).await;
// Asynchronous synchronization
global().synchronize(|duration| async move {
// This should be a sleep call, e.g. using tokio::time::sleep.
std::future::pending().await
}).await;
}
§Gotchas
- Avoid blocking or long-running operations in critical sections as they can delay writers or cause deadlocks.
- Never call
synchronize
orsynchronize_blocking
from within a critical section (will panic). - For best performance, ensure all threads in your process call
quiesce
when a thread is going to sleep or block.
§Implementation Notes
On Windows and Linux, the read-side critical section avoids any processor
memory barriers. It achieves this by having the write side broadcast a
memory barrier to all threads in the process when needed for
synchronization, via the membarrier
syscall on Linux and
FlushProcessWriteBuffers
on Windows.
On other platforms, which do not support this functionality, the read-side critical section uses a memory fence. This makes the read side more expensive on these platforms, but it is still cheaper than a mutex or reader-writer lock.
Structs§
- RcuDomain
- An RCU synchronization domain.
Functions§
- global
- The global RCU domain.