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;
} base_cache;
typedef struct cache_object_link {
struct cache_object_link *next;
} cache_object_link;
typedef struct cache_slab {
void *pages;
size_t count, size;
size_t offset;
cache_object_link *free;
struct cache_object_link *free;
struct list_link link;
} cache_slab;
+1
View File
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src system kernel slab ;
UsePrivateHeaders [ FDirName kernel slab ] ;
KernelMergeObject kernel_slab.o :
interface.cpp
Slab.cpp
: $(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;
// all the AbstractCache stuff is used with the C interface, we
// should probably move this to its own file.
class AbstractCache {
public:
virtual ~AbstractCache() {}
virtual void *Allocate(uint32_t flags) = 0;
virtual void Return(void *object) = 0;
};
typedef struct cache_object_link {
struct cache_object_link *next;
} cache_object_link;
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); }
};
static depot_magazine *_AllocMagazine();
static void _FreeMagazine(depot_magazine *magazine);
static depot_magazine *alloc_magazine();
static void free_magazine(depot_magazine *magazine);
template<typename Type> static Type *
SListPop(Type* &head)
_pop(Type* &head)
{
Type *oldHead = head;
head = head->next;
@@ -99,7 +54,7 @@ SListPop(Type* &head)
template<typename Type> static inline void
SListPush(Type* &head, Type *object)
_push(Type* &head, Type *object)
{
object->next = head;
head = object;
@@ -107,14 +62,14 @@ SListPush(Type* &head, Type *object)
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));
}
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)
+ (objectSize - sizeof(cache_object_link)));
@@ -259,7 +214,7 @@ base_cache_allocate_object(base_cache *cache)
} else
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--;
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);
}
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)
{
// 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).",
link, slab, slab->size - slab->count, cache->empty_count);
SListPush(slab->free, link);
_push(slab->free, link);
slab->count++;
if (slab->count == slab->size) {
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;
}
@@ -396,30 +351,30 @@ base_cache_destruct_slab(base_cache *cache, cache_slab *slab, void *parent,
static inline bool
_IsMagazineEmpty(depot_magazine *magazine)
is_magazine_empty(depot_magazine *magazine)
{
return magazine->current_round == 0;
}
static inline bool
_IsMagazineFull(depot_magazine *magazine)
is_magazine_full(depot_magazine *magazine)
{
return magazine->current_round == magazine->round_count;
}
static inline void *
_PopMagazine(depot_magazine *magazine)
pop_magazine(depot_magazine *magazine)
{
return magazine->rounds[--magazine->current_round];
}
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;
magazine->rounds[magazine->current_round++] = object;
return true;
@@ -427,7 +382,7 @@ _PushMagazine(depot_magazine *magazine, void *object)
static bool
_ExchangeWithFull(base_depot *depot, depot_magazine* &magazine)
exchange_with_full(base_depot *depot, depot_magazine* &magazine)
{
BenaphoreLocker _(depot->lock);
@@ -437,19 +392,19 @@ _ExchangeWithFull(base_depot *depot, depot_magazine* &magazine)
depot->full_count--;
depot->empty_count++;
SListPush(depot->empty, magazine);
magazine = SListPop(depot->full);
_push(depot->empty, magazine);
magazine = _pop(depot->full);
return true;
}
static bool
_ExchangeWithEmpty(base_depot *depot, depot_magazine* &magazine)
exchange_with_empty(base_depot *depot, depot_magazine* &magazine)
{
BenaphoreLocker _(depot->lock);
if (depot->empty == NULL) {
depot->empty = _AllocMagazine();
depot->empty = alloc_magazine();
if (depot->empty == NULL)
return false;
} else {
@@ -457,17 +412,17 @@ _ExchangeWithEmpty(base_depot *depot, depot_magazine* &magazine)
}
if (magazine) {
SListPush(depot->full, magazine);
_push(depot->full, magazine);
depot->full_count++;
}
magazine = SListPop(depot->empty);
magazine = _pop(depot->empty);
return true;
}
static depot_magazine *
_AllocMagazine()
alloc_magazine()
{
depot_magazine *magazine = (depot_magazine *)malloc(sizeof(depot_magazine)
+ kMagazineCapacity * sizeof(void *));
@@ -482,18 +437,18 @@ _AllocMagazine()
static void
_FreeMagazine(depot_magazine *magazine)
free_magazine(depot_magazine *magazine)
{
free(magazine);
}
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++)
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;
while (true) {
if (!_IsMagazineEmpty(store->loaded))
return _PopMagazine(store->loaded);
if (!is_magazine_empty(store->loaded))
return pop_magazine(store->loaded);
if (store->previous && (_IsMagazineFull(store->previous)
|| _ExchangeWithFull(depot, store->previous)))
if (store->previous && (is_magazine_full(store->previous)
|| exchange_with_full(depot, store->previous)))
std::swap(store->previous, store->loaded);
else
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.
while (true) {
if (store->loaded && _PushMagazine(store->loaded, object))
if (store->loaded && push_magazine(store->loaded, object))
return 1;
if ((store->previous && _IsMagazineEmpty(store->previous))
|| _ExchangeWithEmpty(depot, store->previous))
if ((store->previous && is_magazine_empty(store->previous))
|| exchange_with_empty(depot, store->previous))
std::swap(store->loaded, store->previous);
else
return 0;
@@ -600,60 +555,16 @@ base_depot_make_empty(base_depot *depot)
for (int i = 0; i < smp_get_num_cpus(); i++) {
if (depot->stores[i].loaded)
_EmptyMagazine(depot, depot->stores[i].loaded);
empty_magazine(depot, depot->stores[i].loaded);
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;
}
while (depot->full)
_EmptyMagazine(depot, SListPop(depot->full));
empty_magazine(depot, _pop(depot->full));
while (depot->empty)
_EmptyMagazine(depot, SListPop(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;
empty_magazine(depot, _pop(depot->empty));
}
+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;
}