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
16RANGE_MARKER_FUNCTION_BEGIN(SlabSmallObjectCache)
17
18
19static inline slab *
20slab_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*
29SmallObjectCache::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
59void
60SmallObjectCache::Delete()
61{
62	this->~SmallObjectCache();
63	slab_internal_free(this, 0);
64}
65
66
67slab*
68SmallObjectCache::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
93void
94SmallObjectCache::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
105slab*
106SmallObjectCache::ObjectSlab(void* object) const
107{
108	return slab_in_pages(lower_boundary(object, slab_size), slab_size);
109}
110
111
112RANGE_MARKER_FUNCTION_END(SlabSmallObjectCache)
113