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 error:: { code:: * , Result } ,
@@ -107,6 +108,7 @@ struct SlotAllocatorInner<T: SlotItem> {
107108 slots : KVec < Option < Entry < T > > > ,
108109 get_count : u64 ,
109110 drop_count : u64 ,
111+ slot_limit : usize ,
110112}
111113
112114/// A single slot allocator instance.
@@ -155,6 +157,7 @@ impl<T: SlotItem> SlotAllocator<T> {
155157 slots,
156158 get_count : 0 ,
157159 drop_count : 0 ,
160+ slot_limit : usize:: MAX ,
158161 } ;
159162
160163 let alloc = Arc :: pin_init (
@@ -176,6 +179,13 @@ impl<T: SlotItem> SlotAllocator<T> {
176179 cb ( & mut inner. data )
177180 }
178181
182+ /// Set the slot limit for this allocator. New bindings will not use slots above
183+ /// this threshold.
184+ pub ( crate ) fn set_limit ( & self , limit : Option < NonZeroUsize > ) {
185+ let mut inner = self . 0 . inner . lock ( ) ;
186+ inner. slot_limit = limit. unwrap_or ( NonZeroUsize :: MAX ) . get ( ) ;
187+ }
188+
179189 /// Gets a fresh slot, optionally reusing a previous allocation if a `SlotToken` is provided.
180190 ///
181191 /// Blocks if no slots are free.
@@ -199,18 +209,20 @@ impl<T: SlotItem> SlotAllocator<T> {
199209 let mut inner = self . 0 . inner . lock ( ) ;
200210
201211 if let Some ( token) = token {
202- let slot = & mut inner. slots [ token. slot as usize ] ;
203- if slot. is_some ( ) {
204- let count = slot. as_ref ( ) . unwrap ( ) . get_time ;
205- if count == token. time {
206- let mut guard = Guard {
207- item : Some ( slot. take ( ) . unwrap ( ) . item ) ,
208- token,
209- changed : false ,
210- alloc : self . 0 . clone ( ) ,
211- } ;
212- cb ( & mut inner. data , & mut guard) ?;
213- return Ok ( guard) ;
212+ if ( token. slot as usize ) < inner. slot_limit {
213+ let slot = & mut inner. slots [ token. slot as usize ] ;
214+ if slot. is_some ( ) {
215+ let count = slot. as_ref ( ) . unwrap ( ) . get_time ;
216+ if count == token. time {
217+ let mut guard = Guard {
218+ item : Some ( slot. take ( ) . unwrap ( ) . item ) ,
219+ token,
220+ changed : false ,
221+ alloc : self . 0 . clone ( ) ,
222+ } ;
223+ cb ( & mut inner. data , & mut guard) ?;
224+ return Ok ( guard) ;
225+ }
214226 }
215227 }
216228 }
@@ -221,6 +233,9 @@ impl<T: SlotItem> SlotAllocator<T> {
221233 let mut oldest_slot = 0u32 ;
222234
223235 for ( i, slot) in inner. slots . iter ( ) . enumerate ( ) {
236+ if i >= inner. slot_limit {
237+ break ;
238+ }
224239 if let Some ( slot) = slot. as_ref ( ) {
225240 if slot. drop_time < oldest_time {
226241 oldest_slot = i as u32 ;
@@ -230,7 +245,7 @@ impl<T: SlotItem> SlotAllocator<T> {
230245 }
231246
232247 if oldest_time == u64:: MAX {
233- if first {
248+ if first && inner . slot_limit == usize :: MAX {
234249 pr_warn ! (
235250 "{}: out of slots, blocking\n " ,
236251 core:: any:: type_name:: <Self >( )
0 commit comments