diff --git a/headers/private/kernel/slab/Base.h b/headers/private/kernel/slab/Base.h index 06e5d037ef..69edca16e8 100644 --- a/headers/private/kernel/slab/Base.h +++ b/headers/private/kernel/slab/Base.h @@ -46,6 +46,9 @@ void delete_object_cache(object_cache *cache); void *object_cache_alloc(object_cache *cache, uint32 flags); void object_cache_free(object_cache *cache, void *object); +status_t object_cache_reserve(object_cache *cache, size_t object_count, + uint32 flags); + #ifdef __cplusplus } #endif diff --git a/src/system/kernel/slab/Slab.cpp b/src/system/kernel/slab/Slab.cpp index 8e171c2638..674a3eb77b 100644 --- a/src/system/kernel/slab/Slab.cpp +++ b/src/system/kernel/slab/Slab.cpp @@ -158,6 +158,8 @@ static benaphore sObjectCacheListLock; static uint8 *sInitialBegin, *sInitialLimit, *sInitialPointer; +static status_t object_cache_reserve_internal(object_cache *cache, + size_t object_count, uint32 flags); static status_t object_depot_init_locks(object_depot *depot); static depot_magazine *alloc_magazine(); static void free_magazine(depot_magazine *magazine); @@ -558,16 +560,14 @@ object_cache_alloc(object_cache *cache, uint32 flags) if (cache->partial.IsEmpty()) { if (cache->empty.IsEmpty()) { - source = cache->CreateSlab(flags); - if (source == NULL) + if (object_cache_reserve_internal(cache, 1, flags) < B_OK) return NULL; cache->pressure++; - } else { - source = cache->empty.RemoveHead(); - cache->empty_count--; } + source = cache->empty.RemoveHead(); + cache->empty_count--; cache->partial.Add(source); } else { source = cache->partial.Head(); @@ -635,6 +635,38 @@ object_cache_free(object_cache *cache, void *object) } +static status_t +object_cache_reserve_internal(object_cache *cache, size_t object_count, + uint32 flags) +{ + size_t numBytes = object_count * cache->object_size; + size_t slabCount = ((numBytes - 1) / cache->slab_size) + 1; + + while (slabCount > 0) { + slab *newSlab = cache->CreateSlab(flags); + if (newSlab == NULL) + return B_NO_MEMORY; + + cache->empty.Add(newSlab); + cache->empty_count++; + slabCount--; + } + + return B_OK; +} + + +status_t +object_cache_reserve(object_cache *cache, size_t object_count, uint32 flags) +{ + if (object_count == 0) + return B_OK; + + BenaphoreLocker _(cache->lock); + return object_cache_reserve_internal(cache, object_count, flags); +} + + slab * object_cache::InitSlab(slab *slab, void *pages, size_t byteCount) {