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
15RANGE_MARKER_FUNCTION_BEGIN(SlabSmallObjectCache)
16
17
18static inline slab *
19slab_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*
26SmallObjectCache::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
56void
57SmallObjectCache::Delete()
58{
59	this->~SmallObjectCache();
60	slab_internal_free(this, 0);
61}
62
63
64slab*
65SmallObjectCache::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
90void
91SmallObjectCache::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
102slab*
103SmallObjectCache::ObjectSlab(void* object) const
104{
105	return slab_in_pages(lower_boundary(object, slab_size), slab_size);
106}
107
108
109RANGE_MARKER_FUNCTION_END(SlabSmallObjectCache)
110