From 7ce72b986c1dfa844e8362a45dcec078aea91d56 Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Thu, 21 Aug 2008 23:02:08 +0000 Subject: [PATCH] * Implement CACHE_DONT_SLEEP partially. At least for small object caches without object depot it should be complete. For the other stuff internal_alloc() would need to pass the flag on to block_alloc(), but that isn't possible yet. * Adjusted the low memory handler to respect the minimum object reserve of the object caches. The swap_test_heap test does seem to pass reliably with 128 MB RAM and 128 MB allocation, now. It's quite slow, though. Particularly while the allocation is filled, the system is completely unusable. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@27118 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/slab/Slab.cpp | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/slab/Slab.cpp b/src/system/kernel/slab/Slab.cpp index bf99f1a999..4408dbeba0 100644 --- a/src/system/kernel/slab/Slab.cpp +++ b/src/system/kernel/slab/Slab.cpp @@ -27,6 +27,7 @@ #include #include #include +#include // TODO kMagazineCapacity should be dynamically tuned per cache. @@ -422,6 +423,7 @@ internal_alloc(size_t size, uint32 flags) return buffer; } + // TODO: Support CACHE_DONT_SLEEP! return block_alloc(size); } @@ -459,8 +461,10 @@ area_allocate_pages(object_cache *cache, void **pages, uint32 flags, // if we are allocating, it is because we need the pages immediatly // so we lock them. when moving the slab to the empty list we should // unlock them, and lock them again when getting one from the empty list. - area_id areaId = create_area(cache->name, pages, addressSpec, - cache->slab_size, lock, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA); + area_id areaId = vm_create_anonymous_area(vm_kernel_address_space_id(), + cache->name, pages, addressSpec, cache->slab_size, lock, + B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, + (flags & CACHE_DONT_SLEEP) != 0 ? CREATE_AREA_DONT_WAIT : 0, true); if (unlockWhileAllocating) cache->Lock(); @@ -561,6 +565,22 @@ object_cache_low_memory(void *_self, uint32 resources, int32 level) break; } + // If the object cache has minimum object reserve, make sure that we don't + // free too many slabs. + if (cache->min_object_reserve > 0 && cache->empty_count > 0) { + size_t objectsPerSlab = cache->empty.Head()->size; + size_t freeObjects = cache->total_objects - cache->used_count; + + if (cache->min_object_reserve + objectsPerSlab >= freeObjects) + return; + + size_t slabsToFree = (freeObjects - cache->min_object_reserve) + / objectsPerSlab; + + if (cache->empty_count > minimumAllowed + slabsToFree) + minimumAllowed = cache->empty_count - slabsToFree; + } + if (cache->empty_count <= minimumAllowed) return;