rust/kernel/id_pool.rs

Source file repositories/reference/linux-study-clean/rust/kernel/id_pool.rs

File Facts

System
Linux kernel
Corpus path
rust/kernel/id_pool.rs
Extension
.rs
Size
9290 bytes
Lines
296
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.

Dependency Surface

Detected Declarations

Annotated Snippet

pub fn shrink(&mut self, mut resizer: PoolResizer) {
        // Between request to shrink that led to allocation of `resizer` and now,
        // bits may have changed.
        // Verify that shrinking is still possible. In case shrinking to
        // the size of `resizer` is no longer possible, do nothing,
        // drop `resizer` and move on.
        let Some(updated) = self.shrink_request() else {
            return;
        };
        if updated.num_ids > resizer.new.len() {
            return;
        }

        resizer.new.copy_and_extend(&self.map);
        self.map = resizer.new;
    }

    /// Returns a [`ReallocRequest`] for growing this [`IdPool`], if possible.
    ///
    /// The capacity of an [`IdPool`] cannot be grown above [`MAX_LEN`].
    ///
    /// [`MAX_LEN`]: BitmapVec::MAX_LEN
    #[inline]
    pub fn grow_request(&self) -> Option<ReallocRequest> {
        let num_ids = self.capacity() * 2;
        if num_ids > BitmapVec::MAX_LEN {
            return None;
        }
        Some(ReallocRequest { num_ids })
    }

    /// Grows pool by using a new [`BitmapVec`], if still necessary.
    ///
    /// The `resizer` arguments has to be obtained by calling [`Self::grow_request`]
    /// on this object and performing a [`ReallocRequest::realloc`].
    #[inline]
    pub fn grow(&mut self, mut resizer: PoolResizer) {
        // Between request to grow that led to allocation of `resizer` and now,
        // another thread may have already grown the capacity.
        // In this case, do nothing, drop `resizer` and move on.
        if resizer.new.len() <= self.capacity() {
            return;
        }

        resizer.new.copy_and_extend(&self.map);
        self.map = resizer.new;
    }

    /// Finds an unused ID in the bitmap.
    ///
    /// Upon success, returns its index. Otherwise, returns [`None`]
    /// to indicate that a [`Self::grow_request`] is needed.
    #[inline]
    #[must_use]
    pub fn find_unused_id(&mut self, offset: usize) -> Option<UnusedId<'_>> {
        // INVARIANT: `next_zero_bit()` returns None or an integer less than `map.len()`
        Some(UnusedId {
            id: self.map.next_zero_bit(offset)?,
            pool: self,
        })
    }

    /// Releases an ID.
    #[inline]
    pub fn release_id(&mut self, id: usize) {
        self.map.clear_bit(id);
    }
}

/// Represents an unused id in an [`IdPool`].
///
/// # Invariants
///
/// The value of `id` is less than `pool.map.len()`.
pub struct UnusedId<'pool> {
    id: usize,
    pool: &'pool mut IdPool,
}

impl<'pool> UnusedId<'pool> {
    /// Get the unused id as an usize.
    ///
    /// Be aware that the id has not yet been acquired in the pool. The
    /// [`acquire`] method must be called to prevent others from taking the id.
    ///
    /// [`acquire`]: UnusedId::acquire()
    #[inline]
    #[must_use]
    pub fn as_usize(&self) -> usize {
        self.id

Annotation

Implementation Notes