rust/kernel/sync/lock.rs
Source file repositories/reference/linux-study-clean/rust/kernel/sync/lock.rs
File Facts
- System
- Linux kernel
- Corpus path
rust/kernel/sync/lock.rs- Extension
.rs- Size
- 11037 bytes
- Lines
- 325
- Domain
- Rust Kernel Layer
- Bucket
- Rust API Membrane
- Inferred role
- Rust Kernel Layer: implementation source
- Status
- source implementation candidate
Why This File Exists
Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.
- Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
- No C-style include directives detected by the generator.
Detected Declarations
function relockfunction deref
Annotated Snippet
unsafe fn relock(ptr: *mut Self::State, guard_state: &mut Self::GuardState) {
// SAFETY: The safety requirements ensure that the lock is initialised.
*guard_state = unsafe { Self::lock(ptr) };
}
/// Asserts that the lock is held using lockdep.
///
/// # Safety
///
/// Callers must ensure that [`Backend::init`] has been previously called.
unsafe fn assert_is_held(ptr: *mut Self::State);
}
/// A mutual exclusion primitive.
///
/// Exposes one of the kernel locking primitives. Which one is exposed depends on the lock
/// [`Backend`] specified as the generic parameter `B`.
#[repr(C)]
#[pin_data]
pub struct Lock<T: ?Sized, B: Backend> {
/// The kernel lock object.
#[pin]
state: Opaque<B::State>,
/// Some locks are known to be self-referential (e.g., mutexes), while others are architecture
/// or config defined (e.g., spinlocks). So we conservatively require them to be pinned in case
/// some architecture uses self-references now or in the future.
#[pin]
_pin: PhantomPinned,
/// The data protected by the lock.
#[pin]
pub(crate) data: UnsafeCell<T>,
}
// SAFETY: `Lock` can be transferred across thread boundaries iff the data it protects can.
unsafe impl<T: ?Sized + Send, B: Backend> Send for Lock<T, B> {}
// SAFETY: `Lock` serialises the interior mutability it provides, so it is `Sync` as long as the
// data it protects is `Send`.
unsafe impl<T: ?Sized + Send, B: Backend> Sync for Lock<T, B> {}
impl<T, B: Backend> Lock<T, B> {
/// Constructs a new lock initialiser.
pub fn new(
t: impl PinInit<T>,
name: &'static CStr,
key: Pin<&'static LockClassKey>,
) -> impl PinInit<Self> {
pin_init!(Self {
data <- UnsafeCell::pin_init(t),
_pin: PhantomPinned,
// SAFETY: `slot` is valid while the closure is called and both `name` and `key` have
// static lifetimes so they live indefinitely.
state <- Opaque::ffi_init(|slot| unsafe {
B::init(slot, name.as_char_ptr(), key.as_ptr())
}),
})
}
}
impl<B: Backend> Lock<(), B> {
/// Constructs a [`Lock`] from a raw pointer.
///
/// This can be useful for interacting with a lock which was initialised outside of Rust.
///
/// # Safety
///
/// The caller promises that `ptr` points to a valid initialised instance of [`State`] during
/// the whole lifetime of `'a`.
///
/// [`State`]: Backend::State
#[inline]
pub unsafe fn from_raw<'a>(ptr: *mut B::State) -> &'a Self {
// SAFETY:
// - By the safety contract `ptr` must point to a valid initialised instance of `B::State`
// - Since the lock data type is `()` which is a ZST, `state` is the only non-ZST member of
// the struct
// - Combined with `#[repr(C)]`, this guarantees `Self` has an equivalent data layout to
// `B::State`.
unsafe { &*ptr.cast() }
}
}
impl<T: ?Sized, B: Backend> Lock<T, B> {
/// Acquires the lock and gives the caller access to the data protected by it.
#[inline]
pub fn lock(&self) -> Guard<'_, T, B> {
// SAFETY: The constructor of the type calls `init`, so the existence of the object proves
// that `init` was called.
Annotation
- Detected declarations: `function relock`, `function deref`.
- Atlas domain: Rust Kernel Layer / Rust API Membrane.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.