some slab cleanups, split the C interface to another file.

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20875 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos
2007-04-28 09:37:38 +00:00
parent 4e8a1b331f
commit 8a96ba39e3
4 changed files with 143 additions and 135 deletions
+1 -5
View File
@@ -51,15 +51,11 @@ typedef struct base_cache {
void *cookie; void *cookie;
} base_cache; } base_cache;
typedef struct cache_object_link {
struct cache_object_link *next;
} cache_object_link;
typedef struct cache_slab { typedef struct cache_slab {
void *pages; void *pages;
size_t count, size; size_t count, size;
size_t offset; size_t offset;
cache_object_link *free; struct cache_object_link *free;
struct list_link link; struct list_link link;
} cache_slab; } cache_slab;
+1
View File
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src system kernel slab ;
UsePrivateHeaders [ FDirName kernel slab ] ; UsePrivateHeaders [ FDirName kernel slab ] ;
KernelMergeObject kernel_slab.o : KernelMergeObject kernel_slab.o :
interface.cpp
Slab.cpp Slab.cpp
: $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused : $(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
+41 -130
View File
@@ -36,61 +36,16 @@ static const int kMagazineCapacity = 32;
static const size_t kCacheColorPeriod = 8; static const size_t kCacheColorPeriod = 8;
typedef struct cache_object_link {
// all the AbstractCache stuff is used with the C interface, we struct cache_object_link *next;
// should probably move this to its own file. } cache_object_link;
class AbstractCache {
public:
virtual ~AbstractCache() {}
virtual void *Allocate(uint32_t flags) = 0;
virtual void Return(void *object) = 0;
};
typedef MergedLinkCacheStrategy<AreaBackend> SmallObjectStrategy; static depot_magazine *alloc_magazine();
typedef HashCacheStrategy<AreaBackend> LargeObjectStrategy; static void free_magazine(depot_magazine *magazine);
typedef Cache<SmallObjectStrategy> SmallObjectCache;
typedef Cache<LargeObjectStrategy> LargeObjectCache;
class SmallObjectAbstractCache : public AbstractCache,
public LocalCache<SmallObjectCache> {
public:
typedef LocalCache<SmallObjectCache> Base;
SmallObjectAbstractCache(const char *name, size_t objectSize,
size_t alignment, base_cache_constructor constructor,
base_cache_destructor destructor, void *cookie)
: Base(name, objectSize, alignment, constructor, destructor, cookie) {}
void *Allocate(uint32_t flags) { return Base::Alloc(flags); }
void Return(void *object) { Base::Free(object); }
};
class LargeObjectAbstractCache : public AbstractCache,
public LocalCache<LargeObjectCache> {
public:
typedef LocalCache<LargeObjectCache> Base;
LargeObjectAbstractCache(const char *name, size_t objectSize,
size_t alignment, base_cache_constructor constructor,
base_cache_destructor destructor, void *cookie)
: Base(name, objectSize, alignment, constructor, destructor, cookie) {}
void *Allocate(uint32_t flags) { return Base::Alloc(flags); }
void Return(void *object) { Base::Free(object); }
};
static depot_magazine *_AllocMagazine();
static void _FreeMagazine(depot_magazine *magazine);
template<typename Type> static Type * template<typename Type> static Type *
SListPop(Type* &head) _pop(Type* &head)
{ {
Type *oldHead = head; Type *oldHead = head;
head = head->next; head = head->next;
@@ -99,7 +54,7 @@ SListPop(Type* &head)
template<typename Type> static inline void template<typename Type> static inline void
SListPush(Type* &head, Type *object) _push(Type* &head, Type *object)
{ {
object->next = head; object->next = head;
head = object; head = object;
@@ -107,14 +62,14 @@ SListPush(Type* &head, Type *object)
static inline void * static inline void *
_LinkToObject(cache_object_link *link, size_t objectSize) link_to_object(cache_object_link *link, size_t objectSize)
{ {
return ((uint8_t *)link) - (objectSize - sizeof(cache_object_link)); return ((uint8_t *)link) - (objectSize - sizeof(cache_object_link));
} }
static inline cache_object_link * static inline cache_object_link *
_ObjectToLink(void *object, size_t objectSize) object_to_link(void *object, size_t objectSize)
{ {
return (cache_object_link *)(((uint8_t *)object) return (cache_object_link *)(((uint8_t *)object)
+ (objectSize - sizeof(cache_object_link))); + (objectSize - sizeof(cache_object_link)));
@@ -259,7 +214,7 @@ base_cache_allocate_object(base_cache *cache)
} else } else
slab = (cache_slab *)list_get_first_item(&cache->partial); slab = (cache_slab *)list_get_first_item(&cache->partial);
cache_object_link *link = SListPop(slab->free); cache_object_link *link = _pop(slab->free);
slab->count--; slab->count--;
TRACE_CACHE(cache, "allocate %p from %p, %lu remaining.", link, slab, TRACE_CACHE(cache, "allocate %p from %p, %lu remaining.", link, slab,
@@ -271,7 +226,7 @@ base_cache_allocate_object(base_cache *cache)
list_add_item(&cache->full, slab); list_add_item(&cache->full, slab);
} }
return _LinkToObject(link, cache->object_size); return link_to_object(link, cache->object_size);
} }
@@ -289,12 +244,12 @@ base_cache_return_object(base_cache *cache, cache_slab *slab,
void *object) void *object)
{ {
// We return true if the slab is completely unused. // We return true if the slab is completely unused.
cache_object_link *link = _ObjectToLink(object, cache->object_size); cache_object_link *link = object_to_link(object, cache->object_size);
TRACE_CACHE(cache, "returning %p to %p, %lu used (%lu empty slabs).", TRACE_CACHE(cache, "returning %p to %p, %lu used (%lu empty slabs).",
link, slab, slab->size - slab->count, cache->empty_count); link, slab, slab->size - slab->count, cache->empty_count);
SListPush(slab->free, link); _push(slab->free, link);
slab->count++; slab->count++;
if (slab->count == slab->size) { if (slab->count == slab->size) {
list_remove_item(&cache->partial, slab); list_remove_item(&cache->partial, slab);
@@ -366,7 +321,7 @@ base_cache_construct_slab(base_cache *cache, cache_slab *slab, void *pages,
} }
} }
SListPush(slab->free, _ObjectToLink(data, cache->object_size)); _push(slab->free, object_to_link(data, cache->object_size));
data += cache->object_size; data += cache->object_size;
} }
@@ -396,30 +351,30 @@ base_cache_destruct_slab(base_cache *cache, cache_slab *slab, void *parent,
static inline bool static inline bool
_IsMagazineEmpty(depot_magazine *magazine) is_magazine_empty(depot_magazine *magazine)
{ {
return magazine->current_round == 0; return magazine->current_round == 0;
} }
static inline bool static inline bool
_IsMagazineFull(depot_magazine *magazine) is_magazine_full(depot_magazine *magazine)
{ {
return magazine->current_round == magazine->round_count; return magazine->current_round == magazine->round_count;
} }
static inline void * static inline void *
_PopMagazine(depot_magazine *magazine) pop_magazine(depot_magazine *magazine)
{ {
return magazine->rounds[--magazine->current_round]; return magazine->rounds[--magazine->current_round];
} }
static inline bool static inline bool
_PushMagazine(depot_magazine *magazine, void *object) push_magazine(depot_magazine *magazine, void *object)
{ {
if (_IsMagazineFull(magazine)) if (is_magazine_full(magazine))
return false; return false;
magazine->rounds[magazine->current_round++] = object; magazine->rounds[magazine->current_round++] = object;
return true; return true;
@@ -427,7 +382,7 @@ _PushMagazine(depot_magazine *magazine, void *object)
static bool static bool
_ExchangeWithFull(base_depot *depot, depot_magazine* &magazine) exchange_with_full(base_depot *depot, depot_magazine* &magazine)
{ {
BenaphoreLocker _(depot->lock); BenaphoreLocker _(depot->lock);
@@ -437,19 +392,19 @@ _ExchangeWithFull(base_depot *depot, depot_magazine* &magazine)
depot->full_count--; depot->full_count--;
depot->empty_count++; depot->empty_count++;
SListPush(depot->empty, magazine); _push(depot->empty, magazine);
magazine = SListPop(depot->full); magazine = _pop(depot->full);
return true; return true;
} }
static bool static bool
_ExchangeWithEmpty(base_depot *depot, depot_magazine* &magazine) exchange_with_empty(base_depot *depot, depot_magazine* &magazine)
{ {
BenaphoreLocker _(depot->lock); BenaphoreLocker _(depot->lock);
if (depot->empty == NULL) { if (depot->empty == NULL) {
depot->empty = _AllocMagazine(); depot->empty = alloc_magazine();
if (depot->empty == NULL) if (depot->empty == NULL)
return false; return false;
} else { } else {
@@ -457,17 +412,17 @@ _ExchangeWithEmpty(base_depot *depot, depot_magazine* &magazine)
} }
if (magazine) { if (magazine) {
SListPush(depot->full, magazine); _push(depot->full, magazine);
depot->full_count++; depot->full_count++;
} }
magazine = SListPop(depot->empty); magazine = _pop(depot->empty);
return true; return true;
} }
static depot_magazine * static depot_magazine *
_AllocMagazine() alloc_magazine()
{ {
depot_magazine *magazine = (depot_magazine *)malloc(sizeof(depot_magazine) depot_magazine *magazine = (depot_magazine *)malloc(sizeof(depot_magazine)
+ kMagazineCapacity * sizeof(void *)); + kMagazineCapacity * sizeof(void *));
@@ -482,18 +437,18 @@ _AllocMagazine()
static void static void
_FreeMagazine(depot_magazine *magazine) free_magazine(depot_magazine *magazine)
{ {
free(magazine); free(magazine);
} }
static void static void
_EmptyMagazine(base_depot *depot, depot_magazine *magazine) empty_magazine(base_depot *depot, depot_magazine *magazine)
{ {
for (uint16_t i = 0; i < magazine->current_round; i++) for (uint16_t i = 0; i < magazine->current_round; i++)
depot->return_object(depot, magazine->rounds[i]); depot->return_object(depot, magazine->rounds[i]);
_FreeMagazine(magazine); free_magazine(magazine);
} }
@@ -557,11 +512,11 @@ base_depot_obtain_from_store(base_depot *depot, depot_cpu_store *store)
return NULL; return NULL;
while (true) { while (true) {
if (!_IsMagazineEmpty(store->loaded)) if (!is_magazine_empty(store->loaded))
return _PopMagazine(store->loaded); return pop_magazine(store->loaded);
if (store->previous && (_IsMagazineFull(store->previous) if (store->previous && (is_magazine_full(store->previous)
|| _ExchangeWithFull(depot, store->previous))) || exchange_with_full(depot, store->previous)))
std::swap(store->previous, store->loaded); std::swap(store->previous, store->loaded);
else else
return NULL; return NULL;
@@ -581,11 +536,11 @@ base_depot_return_to_store(base_depot *depot, depot_cpu_store *store,
// we return the object directly to the slab. // we return the object directly to the slab.
while (true) { while (true) {
if (store->loaded && _PushMagazine(store->loaded, object)) if (store->loaded && push_magazine(store->loaded, object))
return 1; return 1;
if ((store->previous && _IsMagazineEmpty(store->previous)) if ((store->previous && is_magazine_empty(store->previous))
|| _ExchangeWithEmpty(depot, store->previous)) || exchange_with_empty(depot, store->previous))
std::swap(store->loaded, store->previous); std::swap(store->loaded, store->previous);
else else
return 0; return 0;
@@ -600,60 +555,16 @@ base_depot_make_empty(base_depot *depot)
for (int i = 0; i < smp_get_num_cpus(); i++) { for (int i = 0; i < smp_get_num_cpus(); i++) {
if (depot->stores[i].loaded) if (depot->stores[i].loaded)
_EmptyMagazine(depot, depot->stores[i].loaded); empty_magazine(depot, depot->stores[i].loaded);
if (depot->stores[i].previous) if (depot->stores[i].previous)
_EmptyMagazine(depot, depot->stores[i].previous); empty_magazine(depot, depot->stores[i].previous);
depot->stores[i].loaded = depot->stores[i].previous = NULL; depot->stores[i].loaded = depot->stores[i].previous = NULL;
} }
while (depot->full) while (depot->full)
_EmptyMagazine(depot, SListPop(depot->full)); empty_magazine(depot, _pop(depot->full));
while (depot->empty) while (depot->empty)
_EmptyMagazine(depot, SListPop(depot->empty)); empty_magazine(depot, _pop(depot->empty));
}
object_cache_t
object_cache_create(const char *name, size_t object_size, size_t alignment,
status_t (*_constructor)(void *, void *), void (*_destructor)(void *,
void *), void *cookie)
{
if (object_size == 0)
return NULL;
else if (object_size <= 256)
return new (std::nothrow) SmallObjectAbstractCache(name, object_size,
alignment, _constructor, _destructor, cookie);
return new (std::nothrow) LargeObjectAbstractCache(name, object_size,
alignment, _constructor, _destructor, cookie);
}
void *
object_cache_alloc(object_cache_t cache)
{
return object_cache_alloc_etc(cache, 0);
}
void *
object_cache_alloc_etc(object_cache_t cache, uint32_t flags)
{
return ((AbstractCache *)cache)->Allocate(flags);
}
void
object_cache_free(object_cache_t cache, void *object)
{
((AbstractCache *)cache)->Return(object);
}
void
object_cache_destroy(object_cache_t cache)
{
delete (AbstractCache *)cache;
} }
+100
View File
@@ -0,0 +1,100 @@
/*
* Copyright 2007, Hugo Santos. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Hugo Santos, [email protected]
*/
#include <Slab.h>
#include <new>
class AbstractCache {
public:
virtual ~AbstractCache() {}
virtual void *Allocate(uint32_t flags) = 0;
virtual void Return(void *object) = 0;
};
typedef MergedLinkCacheStrategy<AreaBackend> SmallObjectStrategy;
typedef HashCacheStrategy<AreaBackend> LargeObjectStrategy;
typedef Cache<SmallObjectStrategy> SmallObjectCache;
typedef Cache<LargeObjectStrategy> LargeObjectCache;
class SmallObjectAbstractCache : public AbstractCache,
public LocalCache<SmallObjectCache> {
public:
typedef LocalCache<SmallObjectCache> Base;
SmallObjectAbstractCache(const char *name, size_t objectSize,
size_t alignment, base_cache_constructor constructor,
base_cache_destructor destructor, void *cookie)
: Base(name, objectSize, alignment, constructor, destructor, cookie) {}
void *Allocate(uint32_t flags) { return Base::Alloc(flags); }
void Return(void *object) { Base::Free(object); }
};
class LargeObjectAbstractCache : public AbstractCache,
public LocalCache<LargeObjectCache> {
public:
typedef LocalCache<LargeObjectCache> Base;
LargeObjectAbstractCache(const char *name, size_t objectSize,
size_t alignment, base_cache_constructor constructor,
base_cache_destructor destructor, void *cookie)
: Base(name, objectSize, alignment, constructor, destructor, cookie) {}
void *Allocate(uint32_t flags) { return Base::Alloc(flags); }
void Return(void *object) { Base::Free(object); }
};
object_cache_t
object_cache_create(const char *name, size_t object_size, size_t alignment,
status_t (*_constructor)(void *, void *), void (*_destructor)(void *,
void *), void *cookie)
{
if (object_size == 0)
return NULL;
else if (object_size <= 256)
return new (std::nothrow) SmallObjectAbstractCache(name, object_size,
alignment, _constructor, _destructor, cookie);
return new (std::nothrow) LargeObjectAbstractCache(name, object_size,
alignment, _constructor, _destructor, cookie);
}
void *
object_cache_alloc(object_cache_t cache)
{
return object_cache_alloc_etc(cache, 0);
}
void *
object_cache_alloc_etc(object_cache_t cache, uint32_t flags)
{
return ((AbstractCache *)cache)->Allocate(flags);
}
void
object_cache_free(object_cache_t cache, void *object)
{
((AbstractCache *)cache)->Return(object);
}
void
object_cache_destroy(object_cache_t cache)
{
delete (AbstractCache *)cache;
}