1515//! of serious system contention most allocation requests will be immediately fulfilled from the
1616//! previous slot without doing an LRU scan.
1717
18+ use core:: num:: NonZeroUsize ;
1819use core:: ops:: { Deref , DerefMut } ;
1920use kernel:: {
2021 alloc:: { flags:: * , vec_ext:: VecExt } ,
@@ -108,6 +109,7 @@ struct SlotAllocatorInner<T: SlotItem> {
108109 slots : Vec < Option < Entry < T > > > ,
109110 get_count : u64 ,
110111 drop_count : u64 ,
112+ slot_limit : usize ,
111113}
112114
113115/// A single slot allocator instance.
@@ -156,6 +158,7 @@ impl<T: SlotItem> SlotAllocator<T> {
156158 slots,
157159 get_count : 0 ,
158160 drop_count : 0 ,
161+ slot_limit : usize:: MAX ,
159162 } ;
160163
161164 let alloc = Arc :: pin_init (
@@ -177,6 +180,13 @@ impl<T: SlotItem> SlotAllocator<T> {
177180 cb ( & mut inner. data )
178181 }
179182
183+ /// Set the slot limit for this allocator. New bindings will not use slots above
184+ /// this threshold.
185+ pub ( crate ) fn set_limit ( & self , limit : Option < NonZeroUsize > ) {
186+ let mut inner = self . 0 . inner . lock ( ) ;
187+ inner. slot_limit = limit. unwrap_or ( NonZeroUsize :: MAX ) . get ( ) ;
188+ }
189+
180190 /// Gets a fresh slot, optionally reusing a previous allocation if a `SlotToken` is provided.
181191 ///
182192 /// Blocks if no slots are free.
@@ -200,18 +210,20 @@ impl<T: SlotItem> SlotAllocator<T> {
200210 let mut inner = self . 0 . inner . lock ( ) ;
201211
202212 if let Some ( token) = token {
203- let slot = & mut inner. slots [ token. slot as usize ] ;
204- if slot. is_some ( ) {
205- let count = slot. as_ref ( ) . unwrap ( ) . get_time ;
206- if count == token. time {
207- let mut guard = Guard {
208- item : Some ( slot. take ( ) . unwrap ( ) . item ) ,
209- token,
210- changed : false ,
211- alloc : self . 0 . clone ( ) ,
212- } ;
213- cb ( & mut inner. data , & mut guard) ?;
214- return Ok ( guard) ;
213+ if ( token. slot as usize ) < inner. slot_limit {
214+ let slot = & mut inner. slots [ token. slot as usize ] ;
215+ if slot. is_some ( ) {
216+ let count = slot. as_ref ( ) . unwrap ( ) . get_time ;
217+ if count == token. time {
218+ let mut guard = Guard {
219+ item : Some ( slot. take ( ) . unwrap ( ) . item ) ,
220+ token,
221+ changed : false ,
222+ alloc : self . 0 . clone ( ) ,
223+ } ;
224+ cb ( & mut inner. data , & mut guard) ?;
225+ return Ok ( guard) ;
226+ }
215227 }
216228 }
217229 }
@@ -222,6 +234,9 @@ impl<T: SlotItem> SlotAllocator<T> {
222234 let mut oldest_slot = 0u32 ;
223235
224236 for ( i, slot) in inner. slots . iter ( ) . enumerate ( ) {
237+ if i >= inner. slot_limit {
238+ break ;
239+ }
225240 if let Some ( slot) = slot. as_ref ( ) {
226241 if slot. drop_time < oldest_time {
227242 oldest_slot = i as u32 ;
@@ -231,7 +246,7 @@ impl<T: SlotItem> SlotAllocator<T> {
231246 }
232247
233248 if oldest_time == u64:: MAX {
234- if first {
249+ if first && inner . slot_limit == usize :: MAX {
235250 pr_warn ! (
236251 "{}: out of slots, blocking\n " ,
237252 core:: any:: type_name:: <Self >( )
0 commit comments