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, flags::GFP_KERNEL};
use kernel::id_pool::IdPool;
let mut pool = IdPool::new(64, GFP_KERNEL)?;
for i in 0..64 {
assert_eq!(i, pool.acquire_next_id(i).ok_or(ENOSPC)?);
}
pool.release_id(23);
assert_eq!(23, pool.acquire_next_id(0).ok_or(ENOSPC)?);
assert_eq!(None, pool.acquire_next_id(0)); // time to realloc.
let resizer = pool.grow_request().ok_or(ENOSPC)?.realloc(GFP_KERNEL)?;
pool.grow(resizer);
assert_eq!(pool.acquire_next_id(0), Some(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.acquire_next_id(0) {
Some(index) => return Ok(index),
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(num_ids: usize, flags: Flags) -> Result<Self, AllocError>
pub fn new(num_ids: usize, flags: Flags) -> Result<Self, AllocError>
Constructs a new IdPool
.
A capacity below BITS_PER_LONG
is adjusted to
BITS_PER_LONG
.
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 BITS_PER_LONG
.
§Examples
use kernel::alloc::{AllocError, flags::GFP_KERNEL};
use kernel::id_pool::{ReallocRequest, IdPool};
let mut pool = IdPool::new(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(), kernel::bindings::BITS_PER_LONG as usize);
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 acquire_next_id(&mut self, offset: usize) -> Option<usize>
pub fn acquire_next_id(&mut self, offset: usize) -> Option<usize>
Acquires a new ID by finding and setting the next zero bit 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.
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