1a30fb13fSHugo Santos/*
2a30fb13fSHugo Santos * Copyright 2007, Hugo Santos. All Rights Reserved.
3a30fb13fSHugo Santos * Distributed under the terms of the MIT License.
4a30fb13fSHugo Santos *
5a30fb13fSHugo Santos * Authors:
6a30fb13fSHugo Santos *      Hugo Santos, hugosantos@gmail.com
7a30fb13fSHugo Santos */
8a30fb13fSHugo Santos
9a30fb13fSHugo Santos#include "Slab.h"
10a30fb13fSHugo Santos
11a30fb13fSHugo Santos#include <stdio.h>
12a30fb13fSHugo Santos#include <malloc.h>
13a30fb13fSHugo Santos
14a30fb13fSHugo Santos
15a30fb13fSHugo Santos// TODO this value should be dynamically tuned per cache.
16a30fb13fSHugo Santosstatic const int kMagazineCapacity = 32;
17a30fb13fSHugo Santos
18a30fb13fSHugo Santosstatic const size_t kCacheColorPeriod = 8;
19a30fb13fSHugo Santos
20a30fb13fSHugo Santos
21a30fb13fSHugo Santostemplate<typename Type> static Type *
22a30fb13fSHugo SantosSListPop(Type* &head)
23a30fb13fSHugo Santos{
24a30fb13fSHugo Santos	Type *oldHead = head;
25a30fb13fSHugo Santos	head = head->next;
26a30fb13fSHugo Santos	return oldHead;
27a30fb13fSHugo Santos}
28a30fb13fSHugo Santos
29a30fb13fSHugo Santos
30a30fb13fSHugo Santostemplate<typename Type> static inline void
31a30fb13fSHugo SantosSListPush(Type* &head, Type *object)
32a30fb13fSHugo Santos{
33a30fb13fSHugo Santos	object->next = head;
34a30fb13fSHugo Santos	head = object;
35a30fb13fSHugo Santos}
36a30fb13fSHugo Santos
37a30fb13fSHugo Santos
38a30fb13fSHugo Santosstatus_t
39a30fb13fSHugo SantosMallocBackend::AllocatePages(BaseCache *cache, AllocationID *id, void **pages,
40a30fb13fSHugo Santos	size_t byteCount, uint32_t flags)
41a30fb13fSHugo Santos{
42a30fb13fSHugo Santos	size_t alignment = 16;
43a30fb13fSHugo Santos
44a30fb13fSHugo Santos	if (flags & CACHE_ALIGN_TO_PAGE_TOTAL)
45a30fb13fSHugo Santos		alignment = byteCount;
46a30fb13fSHugo Santos
47a30fb13fSHugo Santos	*pages = memalign(alignment, byteCount);
48a30fb13fSHugo Santos	if (*pages == NULL)
49a30fb13fSHugo Santos		return B_NO_MEMORY;
50a30fb13fSHugo Santos
51a30fb13fSHugo Santos	*id = *pages;
52a30fb13fSHugo Santos	return B_OK;
53a30fb13fSHugo Santos}
54a30fb13fSHugo Santos
55a30fb13fSHugo Santosvoid
56a30fb13fSHugo SantosMallocBackend::FreePages(BaseCache *cache, void *pages)
57a30fb13fSHugo Santos{
58a30fb13fSHugo Santos	free(pages);
59a30fb13fSHugo Santos}
60a30fb13fSHugo Santos
61a30fb13fSHugo Santos
62a30fb13fSHugo Santosstatus_t
63a30fb13fSHugo SantosAreaBackend::AllocatePages(BaseCache *cache, area_id *id, void **pages,
64a30fb13fSHugo Santos	size_t byteCount, uint32_t flags)
65a30fb13fSHugo Santos{
66a30fb13fSHugo Santos	if (flags & CACHE_ALIGN_TO_PAGE_TOTAL)
67a30fb13fSHugo Santos		; // panic()
68a30fb13fSHugo Santos
69a30fb13fSHugo Santos	area_id areaId = create_area(cache->Name(), pages, B_ANY_ADDRESS, //B_ANY_KERNEL_ADDRESS,
70a30fb13fSHugo Santos		byteCount, B_NO_LOCK, B_READ_AREA | B_WRITE_AREA);
71a30fb13fSHugo Santos	if (areaId < 0)
72a30fb13fSHugo Santos		return areaId;
73a30fb13fSHugo Santos
74a30fb13fSHugo Santos	printf("AreaBackend::AllocatePages() = { %ld, %p }\n", areaId, *pages);
75a30fb13fSHugo Santos
76a30fb13fSHugo Santos	*id = areaId;
77a30fb13fSHugo Santos	return B_OK;
78a30fb13fSHugo Santos}
79a30fb13fSHugo Santos
80a30fb13fSHugo Santosvoid
81a30fb13fSHugo SantosAreaBackend::FreePages(BaseCache *cache, area_id area)
82a30fb13fSHugo Santos{
83a30fb13fSHugo Santos	printf("AreaBackend::DeletePages(%ld)\n", area);
84a30fb13fSHugo Santos	delete_area(area);
85a30fb13fSHugo Santos}
86a30fb13fSHugo Santos
87a30fb13fSHugo Santos
88a30fb13fSHugo SantosBaseCache::BaseCache(const char *_name, size_t objectSize, size_t alignment,
89a30fb13fSHugo Santos	Constructor _constructor, Destructor _destructor, void *_cookie)
90a30fb13fSHugo Santos	: fConstructor(_constructor), fDestructor(_destructor), fCookie(_cookie)
91a30fb13fSHugo Santos{
92a30fb13fSHugo Santos	strncpy(fName, _name, sizeof(fName));
93a30fb13fSHugo Santos	fName[sizeof(fName) - 1] = 0;
94a30fb13fSHugo Santos
95a30fb13fSHugo Santos	if (alignment > 0 && (objectSize & (alignment - 1)))
96a30fb13fSHugo Santos		fObjectSize = objectSize + alignment - (objectSize & (alignment - 1));
97a30fb13fSHugo Santos	else
98a30fb13fSHugo Santos		fObjectSize = objectSize;
99a30fb13fSHugo Santos
100a30fb13fSHugo Santos	fCacheColorCycle = 0;
101a30fb13fSHugo Santos}
102a30fb13fSHugo Santos
103a30fb13fSHugo Santos
104a30fb13fSHugo SantosBaseCache::ObjectLink *BaseCache::AllocateObject()
105a30fb13fSHugo Santos{
106a30fb13fSHugo Santos	Slab *slab = fPartialSlabs.Head();
107a30fb13fSHugo Santos
108a30fb13fSHugo Santos	printf("BaseCache::AllocateObject() from %p, %lu remaining\n",
109a30fb13fSHugo Santos		slab, slab->count);
110a30fb13fSHugo Santos
111a30fb13fSHugo Santos	ObjectLink *link = SListPop(slab->free);
112a30fb13fSHugo Santos	slab->count--;
113a30fb13fSHugo Santos	if (slab->count == 0) {
114a30fb13fSHugo Santos		// move the partial slab to the full list
115a30fb13fSHugo Santos		fPartialSlabs.Remove(slab);
116a30fb13fSHugo Santos		fFullSlabs.Add(slab);
117a30fb13fSHugo Santos	}
118a30fb13fSHugo Santos
119a30fb13fSHugo Santos	return link;
120a30fb13fSHugo Santos}
121a30fb13fSHugo Santos
122a30fb13fSHugo Santos
123a30fb13fSHugo Santosbool
124a30fb13fSHugo SantosBaseCache::ReturnObject(const ObjectInfo &object)
125a30fb13fSHugo Santos{
126a30fb13fSHugo Santos	Slab *slab = object.first;
127a30fb13fSHugo Santos	ObjectLink *link = object.second;
128a30fb13fSHugo Santos
129a30fb13fSHugo Santos	// We return true if the slab is completely unused.
130a30fb13fSHugo Santos
131a30fb13fSHugo Santos	SListPush(slab->free, link);
132a30fb13fSHugo Santos	slab->count++;
133a30fb13fSHugo Santos	if (slab->count == slab->size) {
134a30fb13fSHugo Santos		fPartialSlabs.Remove(slab);
135a30fb13fSHugo Santos		return true;
136a30fb13fSHugo Santos	} else if (slab->count == 1) {
137a30fb13fSHugo Santos		fFullSlabs.Remove(slab);
138a30fb13fSHugo Santos		fPartialSlabs.Add(slab);
139a30fb13fSHugo Santos	}
140a30fb13fSHugo Santos
141a30fb13fSHugo Santos	return false;
142a30fb13fSHugo Santos}
143a30fb13fSHugo Santos
144a30fb13fSHugo Santos
145a30fb13fSHugo SantosBaseCache::Slab *
146a30fb13fSHugo SantosBaseCache::ConstructSlab(Slab *slab, void *pages, size_t byteCount,
147a30fb13fSHugo Santos	ObjectLink *(*getLink)(void *parent, void *object), void *parent)
148a30fb13fSHugo Santos{
149a30fb13fSHugo Santos	printf("BaseCache::ConstructSlab(%p, %p, %lu, %p, %p)\n", slab, pages,
150a30fb13fSHugo Santos		byteCount, getLink, parent);
151a30fb13fSHugo Santos
152a30fb13fSHugo Santos	slab->pages = pages;
153a30fb13fSHugo Santos	slab->count = slab->size = byteCount / fObjectSize;
154a30fb13fSHugo Santos	slab->free = NULL;
155a30fb13fSHugo Santos
156a30fb13fSHugo Santos	size_t spareBytes = byteCount - (slab->size * fObjectSize);
157a30fb13fSHugo Santos	size_t cycle = fCacheColorCycle;
158a30fb13fSHugo Santos
159a30fb13fSHugo Santos	if (cycle > spareBytes)
160a30fb13fSHugo Santos		cycle = 0;
161a30fb13fSHugo Santos	else
162a30fb13fSHugo Santos		fCacheColorCycle += kCacheColorPeriod;
163a30fb13fSHugo Santos
164a30fb13fSHugo Santos	printf("  %lu objects, %lu spare bytes, cycle %lu\n",
165a30fb13fSHugo Santos		slab->size, spareBytes, cycle);
166a30fb13fSHugo Santos
167a30fb13fSHugo Santos	uint8_t *data = ((uint8_t *)pages) + cycle;
168a30fb13fSHugo Santos
169a30fb13fSHugo Santos	for (size_t i = 0; i < slab->size; i++) {
170a30fb13fSHugo Santos		if (fConstructor)
171a30fb13fSHugo Santos			fConstructor(fCookie, data);
172a30fb13fSHugo Santos		SListPush(slab->free, getLink(parent, data));
173a30fb13fSHugo Santos		data += fObjectSize;
174a30fb13fSHugo Santos	}
175a30fb13fSHugo Santos
176a30fb13fSHugo Santos	return slab;
177a30fb13fSHugo Santos}
178a30fb13fSHugo Santos
179a30fb13fSHugo Santos
180a30fb13fSHugo Santosvoid
181a30fb13fSHugo SantosBaseCache::DestructSlab(Slab *slab)
182a30fb13fSHugo Santos{
183a30fb13fSHugo Santos	if (fDestructor == NULL)
184a30fb13fSHugo Santos		return;
185a30fb13fSHugo Santos
186a30fb13fSHugo Santos	uint8_t *data = (uint8_t *)slab->pages;
187a30fb13fSHugo Santos
188a30fb13fSHugo Santos	for (size_t i = 0; i < slab->size; i++) {
189a30fb13fSHugo Santos		fDestructor(fCookie, data);
190a30fb13fSHugo Santos		data += fObjectSize;
191a30fb13fSHugo Santos	}
192a30fb13fSHugo Santos}
193a30fb13fSHugo Santos
194a30fb13fSHugo Santos
195a30fb13fSHugo Santosstatic inline bool
196a30fb13fSHugo Santos_IsMagazineEmpty(BaseDepot::Magazine *magazine)
197a30fb13fSHugo Santos{
198a30fb13fSHugo Santos	return magazine->current_round == 0;
199a30fb13fSHugo Santos}
200a30fb13fSHugo Santos
201a30fb13fSHugo Santos
202a30fb13fSHugo Santosstatic inline bool
203a30fb13fSHugo Santos_IsMagazineFull(BaseDepot::Magazine *magazine)
204a30fb13fSHugo Santos{
205a30fb13fSHugo Santos	return magazine->current_round == magazine->round_count;
206a30fb13fSHugo Santos}
207a30fb13fSHugo Santos
208a30fb13fSHugo Santos
209a30fb13fSHugo Santosstatic inline void *
210a30fb13fSHugo Santos_PopMagazine(BaseDepot::Magazine *magazine)
211a30fb13fSHugo Santos{
212a30fb13fSHugo Santos	return magazine->rounds[--magazine->current_round];
213a30fb13fSHugo Santos}
214a30fb13fSHugo Santos
215a30fb13fSHugo Santos
216a30fb13fSHugo Santosstatic inline bool
217a30fb13fSHugo Santos_PushMagazine(BaseDepot::Magazine *magazine, void *object)
218a30fb13fSHugo Santos{
219a30fb13fSHugo Santos	if (_IsMagazineFull(magazine))
220a30fb13fSHugo Santos		return false;
221a30fb13fSHugo Santos	magazine->rounds[magazine->current_round++] = object;
222a30fb13fSHugo Santos	return true;
223a30fb13fSHugo Santos}
224a30fb13fSHugo Santos
225a30fb13fSHugo Santos
226a30fb13fSHugo SantosBaseDepot::BaseDepot()
227a30fb13fSHugo Santos	: fFull(NULL), fEmpty(NULL), fFullCount(0), fEmptyCount(0)
228a30fb13fSHugo Santos{
229a30fb13fSHugo Santos	// benaphore_init(...)
230a30fb13fSHugo Santos	fStores = new (std::nothrow) CPUStore[smp_get_num_cpus()];
231a30fb13fSHugo Santos
232a30fb13fSHugo Santos	if (fStores) {
233a30fb13fSHugo Santos		for (int i = 0; i < smp_get_num_cpus(); i++) {
234a30fb13fSHugo Santos			// benaphore_init(...)
235a30fb13fSHugo Santos			fStores[i].loaded = fStores[i].previous = NULL;
236a30fb13fSHugo Santos		}
237a30fb13fSHugo Santos	}
238a30fb13fSHugo Santos}
239a30fb13fSHugo Santos
240a30fb13fSHugo Santos
241a30fb13fSHugo SantosBaseDepot::~BaseDepot()
242a30fb13fSHugo Santos{
243a30fb13fSHugo Santos	// MakeEmpty may not be used here as ReturnObject is
244a30fb13fSHugo Santos	// no longer available by then.
245a30fb13fSHugo Santos
246a30fb13fSHugo Santos	delete [] fStores;
247a30fb13fSHugo Santos
248a30fb13fSHugo Santos	// benaphore_destroy()
249a30fb13fSHugo Santos}
250a30fb13fSHugo Santos
251a30fb13fSHugo Santos
252a30fb13fSHugo Santosstatus_t
253a30fb13fSHugo SantosBaseDepot::InitCheck() const
254a30fb13fSHugo Santos{
255a30fb13fSHugo Santos	return fStores ? B_OK : B_NO_MEMORY;
256a30fb13fSHugo Santos}
257a30fb13fSHugo Santos
258a30fb13fSHugo Santos
259a30fb13fSHugo Santosvoid *
260a30fb13fSHugo SantosBaseDepot::ObtainFromStore(CPUStore *store)
261a30fb13fSHugo Santos{
262a30fb13fSHugo Santos	BenaphoreLocker _(store->lock);
263a30fb13fSHugo Santos
264a30fb13fSHugo Santos	// To better understand both the Alloc() and Free() logic refer to
265a30fb13fSHugo Santos	// Bonwick's ``Magazines and Vmem'' [in 2001 USENIX proceedings]
266a30fb13fSHugo Santos
267a30fb13fSHugo Santos	// In a nutshell, we try to get an object from the loaded magazine
268a30fb13fSHugo Santos	// if it's not empty, or from the previous magazine if it's full
269a30fb13fSHugo Santos	// and finally from the Slab if the magazine depot has no full magazines.
270a30fb13fSHugo Santos
271a30fb13fSHugo Santos	if (store->loaded == NULL)
272a30fb13fSHugo Santos		return NULL;
273a30fb13fSHugo Santos
274a30fb13fSHugo Santos	while (true) {
275a30fb13fSHugo Santos		if (!_IsMagazineEmpty(store->loaded))
276a30fb13fSHugo Santos			return _PopMagazine(store->loaded);
277a30fb13fSHugo Santos
278a30fb13fSHugo Santos		if (store->previous && (_IsMagazineFull(store->previous)
279a30fb13fSHugo Santos			|| _ExchangeWithFull(store->previous)))
280a30fb13fSHugo Santos			std::swap(store->previous, store->loaded);
281a30fb13fSHugo Santos		else
282a30fb13fSHugo Santos			return NULL;
283a30fb13fSHugo Santos	}
284a30fb13fSHugo Santos}
285a30fb13fSHugo Santos
286a30fb13fSHugo Santos
287a30fb13fSHugo Santosbool
288a30fb13fSHugo SantosBaseDepot::ReturnToStore(CPUStore *store, void *object)
289a30fb13fSHugo Santos{
290a30fb13fSHugo Santos	BenaphoreLocker _(store->lock);
291a30fb13fSHugo Santos
292a30fb13fSHugo Santos	// We try to add the object to the loaded magazine if we have one
293a30fb13fSHugo Santos	// and it's not full, or to the previous one if it is empty. If
294a30fb13fSHugo Santos	// the magazine depot doesn't provide us with a new empty magazine
295a30fb13fSHugo Santos	// we return the object directly to the slab.
296a30fb13fSHugo Santos
297a30fb13fSHugo Santos	while (true) {
298a30fb13fSHugo Santos		if (store->loaded && _PushMagazine(store->loaded, object))
299a30fb13fSHugo Santos			return true;
300a30fb13fSHugo Santos
301a30fb13fSHugo Santos		if ((store->previous && _IsMagazineEmpty(store->previous))
302a30fb13fSHugo Santos			|| _ExchangeWithEmpty(store->previous))
303a30fb13fSHugo Santos			std::swap(store->loaded, store->previous);
304a30fb13fSHugo Santos		else
305a30fb13fSHugo Santos			return false;
306a30fb13fSHugo Santos	}
307a30fb13fSHugo Santos}
308a30fb13fSHugo Santos
309a30fb13fSHugo Santos
310a30fb13fSHugo Santosvoid
311a30fb13fSHugo SantosBaseDepot::MakeEmpty()
312a30fb13fSHugo Santos{
313a30fb13fSHugo Santos	for (int i = 0; i < smp_get_num_cpus(); i++) {
314a30fb13fSHugo Santos		if (fStores[i].loaded)
315a30fb13fSHugo Santos			_EmptyMagazine(fStores[i].loaded);
316a30fb13fSHugo Santos		if (fStores[i].previous)
317a30fb13fSHugo Santos			_EmptyMagazine(fStores[i].previous);
318a30fb13fSHugo Santos		fStores[i].loaded = fStores[i].previous = NULL;
319a30fb13fSHugo Santos	}
320a30fb13fSHugo Santos
321a30fb13fSHugo Santos	while (fFull)
322a30fb13fSHugo Santos		_EmptyMagazine(SListPop(fFull));
323a30fb13fSHugo Santos
324a30fb13fSHugo Santos	while (fEmpty)
325a30fb13fSHugo Santos		_EmptyMagazine(SListPop(fEmpty));
326a30fb13fSHugo Santos}
327a30fb13fSHugo Santos
328a30fb13fSHugo Santos
329a30fb13fSHugo Santosbool
330a30fb13fSHugo SantosBaseDepot::_ExchangeWithFull(Magazine* &magazine)
331a30fb13fSHugo Santos{
332a30fb13fSHugo Santos	BenaphoreLocker _(fLock);
333a30fb13fSHugo Santos
334a30fb13fSHugo Santos	if (fFull == NULL)
335a30fb13fSHugo Santos		return false;
336a30fb13fSHugo Santos
337a30fb13fSHugo Santos	fFullCount--;
338a30fb13fSHugo Santos	fEmptyCount++;
339a30fb13fSHugo Santos
340a30fb13fSHugo Santos	SListPush(fEmpty, magazine);
341a30fb13fSHugo Santos	magazine = SListPop(fFull);
342a30fb13fSHugo Santos	return true;
343a30fb13fSHugo Santos}
344a30fb13fSHugo Santos
345a30fb13fSHugo Santos
346a30fb13fSHugo Santosbool
347a30fb13fSHugo SantosBaseDepot::_ExchangeWithEmpty(Magazine* &magazine)
348a30fb13fSHugo Santos{
349a30fb13fSHugo Santos	BenaphoreLocker _(fLock);
350a30fb13fSHugo Santos
351a30fb13fSHugo Santos	if (fEmpty == NULL) {
352a30fb13fSHugo Santos		fEmpty = _AllocMagazine();
353a30fb13fSHugo Santos		if (fEmpty == NULL)
354a30fb13fSHugo Santos			return false;
355a30fb13fSHugo Santos	} else {
356a30fb13fSHugo Santos		fEmptyCount--;
357a30fb13fSHugo Santos	}
358a30fb13fSHugo Santos
359a30fb13fSHugo Santos	if (magazine) {
360a30fb13fSHugo Santos		SListPush(fFull, magazine);
361a30fb13fSHugo Santos		fFullCount++;
362a30fb13fSHugo Santos	}
363a30fb13fSHugo Santos
364a30fb13fSHugo Santos	magazine = SListPop(fEmpty);
365a30fb13fSHugo Santos	return true;
366a30fb13fSHugo Santos}
367a30fb13fSHugo Santos
368a30fb13fSHugo Santos
369a30fb13fSHugo Santosvoid
370a30fb13fSHugo SantosBaseDepot::_EmptyMagazine(Magazine *magazine)
371a30fb13fSHugo Santos{
372a30fb13fSHugo Santos	for (uint16_t i = 0; i < magazine->current_round; i++)
373a30fb13fSHugo Santos		ReturnObject(magazine->rounds[i]);
374a30fb13fSHugo Santos	_FreeMagazine(magazine);
375a30fb13fSHugo Santos}
376a30fb13fSHugo Santos
377a30fb13fSHugo Santos
378a30fb13fSHugo SantosBaseDepot::Magazine *
379a30fb13fSHugo SantosBaseDepot::_AllocMagazine()
380a30fb13fSHugo Santos{
381a30fb13fSHugo Santos	Magazine *magazine = (Magazine *)malloc(sizeof(Magazine)
382a30fb13fSHugo Santos		+ kMagazineCapacity * sizeof(void *));
383a30fb13fSHugo Santos	if (magazine) {
384a30fb13fSHugo Santos		magazine->next = NULL;
385a30fb13fSHugo Santos		magazine->current_round = 0;
386a30fb13fSHugo Santos		magazine->round_count = kMagazineCapacity;
387a30fb13fSHugo Santos	}
388a30fb13fSHugo Santos
389a30fb13fSHugo Santos	return magazine;
390a30fb13fSHugo Santos}
391a30fb13fSHugo Santos
392a30fb13fSHugo Santos
393a30fb13fSHugo Santosvoid
394a30fb13fSHugo SantosBaseDepot::_FreeMagazine(Magazine *magazine)
395a30fb13fSHugo Santos{
396a30fb13fSHugo Santos	free(magazine);
397a30fb13fSHugo Santos}
398a30fb13fSHugo Santos
399a30fb13fSHugo Santos
400a30fb13fSHugo Santos
401a30fb13fSHugo Santostypedef MergedLinkCacheStrategy<MallocBackend> MallocMergedCacheStrategy;
402a30fb13fSHugo Santostypedef Cache<MallocMergedCacheStrategy> MallocMergedCache;
403a30fb13fSHugo Santostypedef LocalCache<MallocMergedCache> MallocLocalCache;
404a30fb13fSHugo Santos
405a30fb13fSHugo Santostypedef HashCacheStrategy<MallocBackend> MallocHashCacheStrategy;
406a30fb13fSHugo Santostypedef Cache<MallocHashCacheStrategy> MallocHashCache;
407a30fb13fSHugo Santos
408a30fb13fSHugo Santosobject_cache_t
409a30fb13fSHugo Santosobject_cache_create(const char *name, size_t object_size, size_t alignment,
410a30fb13fSHugo Santos	void (*_constructor)(void *, void *), void (*_destructor)(void *, void *),
411a30fb13fSHugo Santos	void *cookie)
412a30fb13fSHugo Santos{
413a30fb13fSHugo Santos	return new (std::nothrow) MallocLocalCache(name, object_size, alignment,
414a30fb13fSHugo Santos		_constructor, _destructor, cookie);
415a30fb13fSHugo Santos}
416a30fb13fSHugo Santos
417a30fb13fSHugo Santos
418a30fb13fSHugo Santosvoid *
419a30fb13fSHugo Santosobject_cache_alloc(object_cache_t cache)
420a30fb13fSHugo Santos{
421a30fb13fSHugo Santos	return ((MallocLocalCache *)cache)->Alloc(0);
422a30fb13fSHugo Santos}
423a30fb13fSHugo Santos
424a30fb13fSHugo Santos
425a30fb13fSHugo Santosvoid *
426a30fb13fSHugo Santosobject_cache_alloc_etc(object_cache_t cache, uint32_t flags)
427a30fb13fSHugo Santos{
428a30fb13fSHugo Santos	return ((MallocLocalCache *)cache)->Alloc(flags);
429a30fb13fSHugo Santos}
430a30fb13fSHugo Santos
431a30fb13fSHugo Santos
432a30fb13fSHugo Santosvoid
433a30fb13fSHugo Santosobject_cache_free(object_cache_t cache, void *object)
434a30fb13fSHugo Santos{
435a30fb13fSHugo Santos	((MallocLocalCache *)cache)->Free(object);
436a30fb13fSHugo Santos}
437a30fb13fSHugo Santos
438a30fb13fSHugo Santos
439a30fb13fSHugo Santosvoid
440a30fb13fSHugo Santosobject_cache_destroy(object_cache_t cache)
441a30fb13fSHugo Santos{
442a30fb13fSHugo Santos	delete (MallocLocalCache *)cache;
443a30fb13fSHugo Santos}
444a30fb13fSHugo Santos
445a30fb13fSHugo Santos
446a30fb13fSHugo Santosvoid test1()
447a30fb13fSHugo Santos{
448a30fb13fSHugo Santos	MallocLocalCache cache("foobar", sizeof(int), 0, NULL, NULL, NULL);
449a30fb13fSHugo Santos
450a30fb13fSHugo Santos	static const int N = 4096;
451a30fb13fSHugo Santos	void *buf[N];
452a30fb13fSHugo Santos
453a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
454a30fb13fSHugo Santos		buf[i] = cache.Alloc(0);
455a30fb13fSHugo Santos
456a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
457a30fb13fSHugo Santos		cache.Free(buf[i]);
458a30fb13fSHugo Santos
459a30fb13fSHugo Santos	cache.Destroy();
460a30fb13fSHugo Santos}
461a30fb13fSHugo Santos
462a30fb13fSHugo Santosvoid test2()
463a30fb13fSHugo Santos{
464a30fb13fSHugo Santos	TypedCache<int, MallocBackend> cache("int cache", 0);
465a30fb13fSHugo Santos
466a30fb13fSHugo Santos	static const int N = 4096;
467a30fb13fSHugo Santos	int *buf[N];
468a30fb13fSHugo Santos
469a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
470a30fb13fSHugo Santos		buf[i] = cache.Alloc(0);
471a30fb13fSHugo Santos
472a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
473a30fb13fSHugo Santos		cache.Free(buf[i]);
474a30fb13fSHugo Santos}
475a30fb13fSHugo Santos
476a30fb13fSHugo Santosvoid test3()
477a30fb13fSHugo Santos{
478a30fb13fSHugo Santos	Cache<HashCacheStrategy<AreaBackend> > cache("512byte hash cache", 512, 0, NULL,
479a30fb13fSHugo Santos		NULL, NULL);
480a30fb13fSHugo Santos
481a30fb13fSHugo Santos	static const int N = 128;
482a30fb13fSHugo Santos	void *buf[N];
483a30fb13fSHugo Santos
484a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
485a30fb13fSHugo Santos		buf[i] = cache.AllocateObject(0);
486a30fb13fSHugo Santos
487a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
488a30fb13fSHugo Santos		cache.ReturnObject(buf[i]);
489a30fb13fSHugo Santos}
490a30fb13fSHugo Santos
491a30fb13fSHugo Santosvoid test4()
492a30fb13fSHugo Santos{
493a30fb13fSHugo Santos	LocalCache<MallocHashCache> cache("foobar", 512, 0, NULL, NULL, NULL);
494a30fb13fSHugo Santos
495a30fb13fSHugo Santos	static const int N = 128;
496a30fb13fSHugo Santos	void *buf[N];
497a30fb13fSHugo Santos
498a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
499a30fb13fSHugo Santos		buf[i] = cache.Alloc(0);
500a30fb13fSHugo Santos
501a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
502a30fb13fSHugo Santos		cache.Free(buf[i]);
503a30fb13fSHugo Santos
504a30fb13fSHugo Santos	cache.Destroy();
505a30fb13fSHugo Santos}
506a30fb13fSHugo Santos
507a30fb13fSHugo Santosvoid test5()
508a30fb13fSHugo Santos{
509a30fb13fSHugo Santos	object_cache_t cache = object_cache_create("foobar", 16, 0,
510a30fb13fSHugo Santos		NULL, NULL, NULL);
511a30fb13fSHugo Santos
512a30fb13fSHugo Santos	static const int N = 1024;
513a30fb13fSHugo Santos	void *buf[N];
514a30fb13fSHugo Santos
515a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
516a30fb13fSHugo Santos		buf[i] = object_cache_alloc(cache);
517a30fb13fSHugo Santos
518a30fb13fSHugo Santos	for (int i = 0; i < N; i++)
519a30fb13fSHugo Santos		object_cache_free(cache, buf[i]);
520a30fb13fSHugo Santos
521a30fb13fSHugo Santos	object_cache_destroy(cache);
522a30fb13fSHugo Santos}
523a30fb13fSHugo Santos
524a30fb13fSHugo Santos
525a30fb13fSHugo Santosint main()
526a30fb13fSHugo Santos{
527a30fb13fSHugo Santos	//test1();
528a30fb13fSHugo Santos	//test2();
529a30fb13fSHugo Santos	test3();
530a30fb13fSHugo Santos	//test4();
531a30fb13fSHugo Santos	//test5();
532a30fb13fSHugo Santos	return 0;
533a30fb13fSHugo Santos}
534