pub struct IdPool { /* private fields */ }Expand description
Represents a dynamic ID pool backed by a BitmapVec.
Clients acquire and release IDs from unset bits in a bitmap.
The capacity of the ID pool may be adjusted by users as needed. The API supports the scenario where users need precise control over the time of allocation of a new backing bitmap, which may require release of spinlock. Due to concurrent updates, all operations are re-verified to determine if the grow or shrink is sill valid.
§Examples
Basic usage
use kernel::alloc::AllocError;
use kernel::id_pool::{IdPool, UnusedId};
let mut pool = IdPool::with_capacity(64, GFP_KERNEL)?;
for i in 0..64 {
assert_eq!(i, pool.find_unused_id(i).ok_or(ENOSPC)?.acquire());
}
pool.release_id(23);
assert_eq!(23, pool.find_unused_id(0).ok_or(ENOSPC)?.acquire());
assert!(pool.find_unused_id(0).is_none()); // time to realloc.
let resizer = pool.grow_request().ok_or(ENOSPC)?.realloc(GFP_KERNEL)?;
pool.grow(resizer);
assert_eq!(pool.find_unused_id(0).ok_or(ENOSPC)?.acquire(), 64);Releasing spinlock to grow the pool
use kernel::alloc::{AllocError, flags::GFP_KERNEL};
use kernel::sync::{new_spinlock, SpinLock};
use kernel::id_pool::IdPool;
fn get_id_maybe_realloc(guarded_pool: &SpinLock<IdPool>) -> Result<usize, AllocError> {
let mut pool = guarded_pool.lock();
loop {
match pool.find_unused_id(0) {
Some(index) => return Ok(index.acquire()),
None => {
let alloc_request = pool.grow_request();
drop(pool);
let resizer = alloc_request.ok_or(AllocError)?.realloc(GFP_KERNEL)?;
pool = guarded_pool.lock();
pool.grow(resizer)
}
}
}
}Implementations§
Source§impl IdPool
impl IdPool
Sourcepub fn new() -> Self
pub fn new() -> Self
Constructs a new IdPool.
The pool will have a capacity of MAX_INLINE_LEN.
Sourcepub fn with_capacity(num_ids: usize, flags: Flags) -> Result<Self, AllocError>
pub fn with_capacity(num_ids: usize, flags: Flags) -> Result<Self, AllocError>
Constructs a new IdPool with space for a specific number of bits.
A capacity below MAX_INLINE_LEN is adjusted to MAX_INLINE_LEN.
Sourcepub fn shrink_request(&self) -> Option<ReallocRequest>
pub fn shrink_request(&self) -> Option<ReallocRequest>
Returns a ReallocRequest if the IdPool can be shrunk, None otherwise.
The capacity of an IdPool cannot be shrunk below MAX_INLINE_LEN.
§Examples
use kernel::{
alloc::AllocError,
bitmap::BitmapVec,
id_pool::{
IdPool,
ReallocRequest,
},
};
let mut pool = IdPool::with_capacity(1024, GFP_KERNEL)?;
let alloc_request = pool.shrink_request().ok_or(AllocError)?;
let resizer = alloc_request.realloc(GFP_KERNEL)?;
pool.shrink(resizer);
assert_eq!(pool.capacity(), BitmapVec::MAX_INLINE_LEN);Sourcepub fn shrink(&mut self, resizer: PoolResizer)
pub fn shrink(&mut self, resizer: PoolResizer)
Shrinks pool by using a new BitmapVec, if still possible.
Sourcepub fn grow_request(&self) -> Option<ReallocRequest>
pub fn grow_request(&self) -> Option<ReallocRequest>
Returns a ReallocRequest for growing this IdPool, if possible.
Sourcepub fn grow(&mut self, resizer: PoolResizer)
pub fn grow(&mut self, resizer: PoolResizer)
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.
Sourcepub fn find_unused_id(&mut self, offset: usize) -> Option<UnusedId<'_>>
pub fn find_unused_id(&mut self, offset: usize) -> Option<UnusedId<'_>>
Finds an unused ID in the bitmap.
Upon success, returns its index. Otherwise, returns None
to indicate that a Self::grow_request is needed.
Sourcepub fn release_id(&mut self, id: usize)
pub fn release_id(&mut self, id: usize)
Releases an ID.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for IdPool
impl RefUnwindSafe for IdPool
impl Send for IdPool
impl Sync for IdPool
impl Unpin for IdPool
impl UnwindSafe for IdPool
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> PinInit<T> for T
impl<T> PinInit<T> for T
Source§unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
unsafe fn __pinned_init(self, slot: *mut T) -> Result<(), Infallible>
slot. Read more