1 /* 2 * Copyright 2008, Axel Dörfler. All Rights Reserved. 3 * Copyright 2007, Hugo Santos. All Rights Reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "SmallObjectCache.h" 10 11 #include "MemoryManager.h" 12 #include "slab_private.h" 13 14 15 RANGE_MARKER_FUNCTION_BEGIN(SlabSmallObjectCache) 16 17 18 static inline slab * 19 slab_in_pages(const void *pages, size_t slab_size) 20 { 21 return (slab *)(((uint8 *)pages) + slab_size - sizeof(slab)); 22 } 23 24 25 /*static*/ SmallObjectCache* 26 SmallObjectCache::Create(const char* name, size_t object_size, 27 size_t alignment, size_t maximum, size_t magazineCapacity, 28 size_t maxMagazineCount, uint32 flags, void* cookie, 29 object_cache_constructor constructor, object_cache_destructor destructor, 30 object_cache_reclaimer reclaimer) 31 { 32 void* buffer = slab_internal_alloc(sizeof(SmallObjectCache), flags); 33 if (buffer == NULL) 34 return NULL; 35 36 SmallObjectCache* cache = new(buffer) SmallObjectCache(); 37 38 if (cache->Init(name, object_size, alignment, maximum, magazineCapacity, 39 maxMagazineCount, flags, cookie, constructor, destructor, 40 reclaimer) != B_OK) { 41 cache->Delete(); 42 return NULL; 43 } 44 45 if ((flags & CACHE_LARGE_SLAB) != 0) 46 cache->slab_size = 1024 * object_size; 47 else 48 cache->slab_size = SLAB_CHUNK_SIZE_SMALL; 49 50 cache->slab_size = MemoryManager::AcceptableChunkSize(cache->slab_size); 51 52 return cache; 53 } 54 55 56 void 57 SmallObjectCache::Delete() 58 { 59 this->~SmallObjectCache(); 60 slab_internal_free(this, 0); 61 } 62 63 64 slab* 65 SmallObjectCache::CreateSlab(uint32 flags) 66 { 67 if (!check_cache_quota(this)) 68 return NULL; 69 70 void* pages; 71 72 Unlock(); 73 status_t error = MemoryManager::Allocate(this, flags, pages); 74 Lock(); 75 76 if (error != B_OK) 77 return NULL; 78 79 slab* newSlab = slab_in_pages(pages, slab_size); 80 size_t byteCount = slab_size - sizeof(slab); 81 if (AllocateTrackingInfos(newSlab, byteCount, flags) != B_OK) { 82 MemoryManager::Free(pages, flags); 83 return NULL; 84 } 85 86 return InitSlab(newSlab, pages, byteCount, flags); 87 } 88 89 90 void 91 SmallObjectCache::ReturnSlab(slab* slab, uint32 flags) 92 { 93 UninitSlab(slab); 94 95 Unlock(); 96 FreeTrackingInfos(slab, flags); 97 MemoryManager::Free(slab->pages, flags); 98 Lock(); 99 } 100 101 102 slab* 103 SmallObjectCache::ObjectSlab(void* object) const 104 { 105 return slab_in_pages(lower_boundary(object, slab_size), slab_size); 106 } 107 108 109 RANGE_MARKER_FUNCTION_END(SlabSmallObjectCache) 110