xref: /haiku/src/system/kernel/slab/SmallObjectCache.cpp (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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