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