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