* HashedObjectCache: Instead of entering the individual objects in the hash
table, we only enter the slab. This also saves us the link object per object.
* Removed the now useless {Prepare,Unprepare}Object() methods.
* SmallObjectCache: Unlock the cache while calling into the MemoryManager. We
need to do that to avoid an indirect violation of the CACHE_DONT_* policy.
* Simplified lower_boundary().
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35285 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -25,15 +25,15 @@ __fls0(size_t value)
|
||||
}
|
||||
|
||||
|
||||
static slab*
|
||||
static HashedSlab*
|
||||
allocate_slab(uint32 flags)
|
||||
{
|
||||
return (slab*)slab_internal_alloc(sizeof(slab), flags);
|
||||
return (HashedSlab*)slab_internal_alloc(sizeof(HashedSlab), flags);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_slab(slab* slab, uint32 flags)
|
||||
free_slab(HashedSlab* slab, uint32 flags)
|
||||
{
|
||||
slab_internal_free(slab, flags);
|
||||
}
|
||||
@@ -83,7 +83,7 @@ HashedObjectCache::Create(const char* name, size_t object_size,
|
||||
cache->slab_size = 8 * object_size;
|
||||
|
||||
cache->slab_size = MemoryManager::AcceptableChunkSize(cache->slab_size);
|
||||
cache->lower_boundary = __fls0(cache->object_size);
|
||||
cache->lower_boundary = __fls0(cache->slab_size);
|
||||
|
||||
return cache;
|
||||
}
|
||||
@@ -105,13 +105,16 @@ HashedObjectCache::CreateSlab(uint32 flags)
|
||||
|
||||
Unlock();
|
||||
|
||||
slab* slab = allocate_slab(flags);
|
||||
HashedSlab* slab = allocate_slab(flags);
|
||||
if (slab != NULL) {
|
||||
void* pages;
|
||||
if (MemoryManager::Allocate(this, flags, pages) == B_OK) {
|
||||
Lock();
|
||||
if (InitSlab(slab, pages, slab_size, flags))
|
||||
if (InitSlab(slab, pages, slab_size, flags)) {
|
||||
hash_table.InsertUnchecked(slab);
|
||||
_ResizeHashTableIfNeeded(flags);
|
||||
return slab;
|
||||
}
|
||||
Unlock();
|
||||
MemoryManager::Free(pages, flags);
|
||||
}
|
||||
@@ -125,9 +128,15 @@ HashedObjectCache::CreateSlab(uint32 flags)
|
||||
|
||||
|
||||
void
|
||||
HashedObjectCache::ReturnSlab(slab* slab, uint32 flags)
|
||||
HashedObjectCache::ReturnSlab(slab* _slab, uint32 flags)
|
||||
{
|
||||
HashedSlab* slab = static_cast<HashedSlab*>(_slab);
|
||||
|
||||
hash_table.RemoveUnchecked(slab);
|
||||
_ResizeHashTableIfNeeded(flags);
|
||||
|
||||
UninitSlab(slab);
|
||||
|
||||
Unlock();
|
||||
MemoryManager::Free(slab->pages, flags);
|
||||
free_slab(slab, flags);
|
||||
@@ -138,51 +147,12 @@ HashedObjectCache::ReturnSlab(slab* slab, uint32 flags)
|
||||
slab*
|
||||
HashedObjectCache::ObjectSlab(void* object) const
|
||||
{
|
||||
Link* link = hash_table.Lookup(object);
|
||||
if (link == NULL) {
|
||||
panic("object cache: requested object %p missing from hash table",
|
||||
object);
|
||||
HashedSlab* slab = hash_table.Lookup(::lower_boundary(object, slab_size));
|
||||
if (slab == NULL) {
|
||||
panic("hash object cache %p: unknown object %p", this, object);
|
||||
return NULL;
|
||||
}
|
||||
return link->parent;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
HashedObjectCache::PrepareObject(slab* source, void* object, uint32 flags)
|
||||
{
|
||||
Link* link = _AllocateLink(flags);
|
||||
if (link == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
link->buffer = object;
|
||||
link->parent = source;
|
||||
|
||||
hash_table.InsertUnchecked(link);
|
||||
_ResizeHashTableIfNeeded(flags);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
HashedObjectCache::UnprepareObject(slab* source, void* object, uint32 flags)
|
||||
{
|
||||
Link* link = hash_table.Lookup(object);
|
||||
if (link == NULL) {
|
||||
panic("object cache: requested object missing from hash table");
|
||||
return;
|
||||
}
|
||||
|
||||
if (link->parent != source) {
|
||||
panic("object cache: slab mismatch");
|
||||
return;
|
||||
}
|
||||
|
||||
hash_table.RemoveUnchecked(link);
|
||||
_ResizeHashTableIfNeeded(flags);
|
||||
|
||||
_FreeLink(link, flags);
|
||||
return slab;
|
||||
}
|
||||
|
||||
|
||||
@@ -208,18 +178,3 @@ HashedObjectCache::_ResizeHashTableIfNeeded(uint32 flags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*static*/ inline HashedObjectCache::Link*
|
||||
HashedObjectCache::_AllocateLink(uint32 flags)
|
||||
{
|
||||
return (HashedObjectCache::Link*)
|
||||
slab_internal_alloc(sizeof(HashedObjectCache::Link), flags);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ inline void
|
||||
HashedObjectCache::_FreeLink(HashedObjectCache::Link* link, uint32 flags)
|
||||
{
|
||||
slab_internal_free(link, flags);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,11 @@
|
||||
#include "slab_private.h"
|
||||
|
||||
|
||||
struct HashedSlab : slab {
|
||||
HashedSlab* hash_next;
|
||||
};
|
||||
|
||||
|
||||
struct HashedObjectCache : ObjectCache {
|
||||
HashedObjectCache();
|
||||
|
||||
@@ -29,22 +34,11 @@ struct HashedObjectCache : ObjectCache {
|
||||
virtual void ReturnSlab(slab* slab, uint32 flags);
|
||||
virtual slab* ObjectSlab(void* object) const;
|
||||
|
||||
virtual status_t PrepareObject(slab* source, void* object,
|
||||
uint32 flags);
|
||||
virtual void UnprepareObject(slab* source, void* object,
|
||||
uint32 flags);
|
||||
|
||||
private:
|
||||
struct Link {
|
||||
const void* buffer;
|
||||
slab* parent;
|
||||
Link* next;
|
||||
};
|
||||
|
||||
struct Definition {
|
||||
typedef HashedObjectCache ParentType;
|
||||
typedef const void* KeyType;
|
||||
typedef Link ValueType;
|
||||
typedef HashedSlab ValueType;
|
||||
|
||||
Definition(HashedObjectCache* parent)
|
||||
:
|
||||
@@ -60,23 +54,23 @@ private:
|
||||
|
||||
size_t HashKey(const void* key) const
|
||||
{
|
||||
return (((const uint8*)key) - ((const uint8*)0))
|
||||
return (addr_t)::lower_boundary(key, parent->slab_size)
|
||||
>> parent->lower_boundary;
|
||||
}
|
||||
|
||||
size_t Hash(Link* value) const
|
||||
size_t Hash(HashedSlab* value) const
|
||||
{
|
||||
return HashKey(value->buffer);
|
||||
return HashKey(value->pages);
|
||||
}
|
||||
|
||||
bool Compare(const void* key, Link* value) const
|
||||
bool Compare(const void* key, HashedSlab* value) const
|
||||
{
|
||||
return value->buffer == key;
|
||||
return value->pages == key;
|
||||
}
|
||||
|
||||
Link*& GetLink(Link* value) const
|
||||
HashedSlab*& GetLink(HashedSlab* value) const
|
||||
{
|
||||
return value->next;
|
||||
return value->hash_next;
|
||||
}
|
||||
|
||||
HashedObjectCache* parent;
|
||||
@@ -102,10 +96,6 @@ private:
|
||||
private:
|
||||
void _ResizeHashTableIfNeeded(uint32 flags);
|
||||
|
||||
static Link* _AllocateLink(uint32 flags);
|
||||
static void _FreeLink(HashedObjectCache::Link* link,
|
||||
uint32 flags);
|
||||
|
||||
private:
|
||||
HashTable hash_table;
|
||||
size_t lower_boundary;
|
||||
|
||||
@@ -133,23 +133,15 @@ ObjectCache::InitSlab(slab* slab, void* pages, size_t byteCount, uint32 flags)
|
||||
CREATE_PARANOIA_CHECK_SET(slab, "slab");
|
||||
|
||||
for (size_t i = 0; i < slab->size; i++) {
|
||||
bool failedOnFirst = false;
|
||||
|
||||
status_t status = PrepareObject(slab, data, flags);
|
||||
if (status < B_OK)
|
||||
failedOnFirst = true;
|
||||
else if (constructor)
|
||||
status_t status = B_OK;
|
||||
if (constructor)
|
||||
status = constructor(cookie, data);
|
||||
|
||||
if (status < B_OK) {
|
||||
if (!failedOnFirst)
|
||||
UnprepareObject(slab, data, flags);
|
||||
|
||||
if (status != B_OK) {
|
||||
data = ((uint8*)pages) + slab->offset;
|
||||
for (size_t j = 0; j < i; j++) {
|
||||
if (destructor)
|
||||
destructor(cookie, data);
|
||||
UnprepareObject(slab, data, flags);
|
||||
data += object_size;
|
||||
}
|
||||
|
||||
@@ -191,25 +183,11 @@ ObjectCache::UninitSlab(slab* slab)
|
||||
for (size_t i = 0; i < slab->size; i++) {
|
||||
if (destructor)
|
||||
destructor(cookie, data);
|
||||
UnprepareObject(slab, data, flags);
|
||||
data += object_size;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
ObjectCache::PrepareObject(slab* source, void* object, uint32 flags)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ObjectCache::UnprepareObject(slab* source, void* object, uint32 flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ObjectCache::ReturnObjectToSlab(slab* source, void* object, uint32 flags)
|
||||
{
|
||||
|
||||
@@ -94,11 +94,6 @@ public:
|
||||
size_t byteCount, uint32 flags);
|
||||
void UninitSlab(slab* slab);
|
||||
|
||||
virtual status_t PrepareObject(slab* source, void* object,
|
||||
uint32 flags);
|
||||
virtual void UnprepareObject(slab* source, void* object,
|
||||
uint32 flags);
|
||||
|
||||
void ReturnObjectToSlab(slab* source, void* object,
|
||||
uint32 flags);
|
||||
|
||||
@@ -127,23 +122,15 @@ object_to_link(void* object, size_t objectSize)
|
||||
}
|
||||
|
||||
|
||||
static inline slab *
|
||||
slab_in_pages(const void *pages, size_t slab_size)
|
||||
static inline void*
|
||||
lower_boundary(const void* object, size_t byteCount)
|
||||
{
|
||||
return (slab *)(((uint8 *)pages) + slab_size - sizeof(slab));
|
||||
}
|
||||
|
||||
|
||||
static inline const void *
|
||||
lower_boundary(void *object, size_t byteCount)
|
||||
{
|
||||
const uint8 *null = (uint8 *)NULL;
|
||||
return null + ((((uint8 *)object) - null) & ~(byteCount - 1));
|
||||
return (void*)((addr_t)object & ~(byteCount - 1));
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
check_cache_quota(ObjectCache *cache)
|
||||
check_cache_quota(ObjectCache* cache)
|
||||
{
|
||||
if (cache->maximum == 0)
|
||||
return true;
|
||||
|
||||
@@ -12,6 +12,13 @@
|
||||
#include "slab_private.h"
|
||||
|
||||
|
||||
static inline slab *
|
||||
slab_in_pages(const void *pages, size_t slab_size)
|
||||
{
|
||||
return (slab *)(((uint8 *)pages) + slab_size - sizeof(slab));
|
||||
}
|
||||
|
||||
|
||||
/*static*/ SmallObjectCache*
|
||||
SmallObjectCache::Create(const char* name, size_t object_size,
|
||||
size_t alignment, size_t maximum, uint32 flags, void* cookie,
|
||||
@@ -57,7 +64,11 @@ SmallObjectCache::CreateSlab(uint32 flags)
|
||||
|
||||
void* pages;
|
||||
|
||||
if (MemoryManager::Allocate(this, flags, pages) != B_OK)
|
||||
Unlock();
|
||||
status_t error = MemoryManager::Allocate(this, flags, pages);
|
||||
Lock();
|
||||
|
||||
if (error != B_OK)
|
||||
return NULL;
|
||||
|
||||
return InitSlab(slab_in_pages(pages, slab_size), pages,
|
||||
@@ -69,7 +80,10 @@ void
|
||||
SmallObjectCache::ReturnSlab(slab* slab, uint32 flags)
|
||||
{
|
||||
UninitSlab(slab);
|
||||
|
||||
Unlock();
|
||||
MemoryManager::Free(slab->pages, flags);
|
||||
Lock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user