* 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)
|
allocate_slab(uint32 flags)
|
||||||
{
|
{
|
||||||
return (slab*)slab_internal_alloc(sizeof(slab), flags);
|
return (HashedSlab*)slab_internal_alloc(sizeof(HashedSlab), flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
free_slab(slab* slab, uint32 flags)
|
free_slab(HashedSlab* slab, uint32 flags)
|
||||||
{
|
{
|
||||||
slab_internal_free(slab, 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 = 8 * object_size;
|
||||||
|
|
||||||
cache->slab_size = MemoryManager::AcceptableChunkSize(cache->slab_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;
|
return cache;
|
||||||
}
|
}
|
||||||
@@ -105,13 +105,16 @@ HashedObjectCache::CreateSlab(uint32 flags)
|
|||||||
|
|
||||||
Unlock();
|
Unlock();
|
||||||
|
|
||||||
slab* slab = allocate_slab(flags);
|
HashedSlab* slab = allocate_slab(flags);
|
||||||
if (slab != NULL) {
|
if (slab != NULL) {
|
||||||
void* pages;
|
void* pages;
|
||||||
if (MemoryManager::Allocate(this, flags, pages) == B_OK) {
|
if (MemoryManager::Allocate(this, flags, pages) == B_OK) {
|
||||||
Lock();
|
Lock();
|
||||||
if (InitSlab(slab, pages, slab_size, flags))
|
if (InitSlab(slab, pages, slab_size, flags)) {
|
||||||
|
hash_table.InsertUnchecked(slab);
|
||||||
|
_ResizeHashTableIfNeeded(flags);
|
||||||
return slab;
|
return slab;
|
||||||
|
}
|
||||||
Unlock();
|
Unlock();
|
||||||
MemoryManager::Free(pages, flags);
|
MemoryManager::Free(pages, flags);
|
||||||
}
|
}
|
||||||
@@ -125,9 +128,15 @@ HashedObjectCache::CreateSlab(uint32 flags)
|
|||||||
|
|
||||||
|
|
||||||
void
|
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);
|
UninitSlab(slab);
|
||||||
|
|
||||||
Unlock();
|
Unlock();
|
||||||
MemoryManager::Free(slab->pages, flags);
|
MemoryManager::Free(slab->pages, flags);
|
||||||
free_slab(slab, flags);
|
free_slab(slab, flags);
|
||||||
@@ -138,51 +147,12 @@ HashedObjectCache::ReturnSlab(slab* slab, uint32 flags)
|
|||||||
slab*
|
slab*
|
||||||
HashedObjectCache::ObjectSlab(void* object) const
|
HashedObjectCache::ObjectSlab(void* object) const
|
||||||
{
|
{
|
||||||
Link* link = hash_table.Lookup(object);
|
HashedSlab* slab = hash_table.Lookup(::lower_boundary(object, slab_size));
|
||||||
if (link == NULL) {
|
if (slab == NULL) {
|
||||||
panic("object cache: requested object %p missing from hash table",
|
panic("hash object cache %p: unknown object %p", this, object);
|
||||||
object);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return link->parent;
|
return slab;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -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"
|
#include "slab_private.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct HashedSlab : slab {
|
||||||
|
HashedSlab* hash_next;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct HashedObjectCache : ObjectCache {
|
struct HashedObjectCache : ObjectCache {
|
||||||
HashedObjectCache();
|
HashedObjectCache();
|
||||||
|
|
||||||
@@ -29,22 +34,11 @@ struct HashedObjectCache : ObjectCache {
|
|||||||
virtual void ReturnSlab(slab* slab, uint32 flags);
|
virtual void ReturnSlab(slab* slab, uint32 flags);
|
||||||
virtual slab* ObjectSlab(void* object) const;
|
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:
|
private:
|
||||||
struct Link {
|
|
||||||
const void* buffer;
|
|
||||||
slab* parent;
|
|
||||||
Link* next;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Definition {
|
struct Definition {
|
||||||
typedef HashedObjectCache ParentType;
|
typedef HashedObjectCache ParentType;
|
||||||
typedef const void* KeyType;
|
typedef const void* KeyType;
|
||||||
typedef Link ValueType;
|
typedef HashedSlab ValueType;
|
||||||
|
|
||||||
Definition(HashedObjectCache* parent)
|
Definition(HashedObjectCache* parent)
|
||||||
:
|
:
|
||||||
@@ -60,23 +54,23 @@ private:
|
|||||||
|
|
||||||
size_t HashKey(const void* key) const
|
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;
|
>> 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;
|
HashedObjectCache* parent;
|
||||||
@@ -102,10 +96,6 @@ private:
|
|||||||
private:
|
private:
|
||||||
void _ResizeHashTableIfNeeded(uint32 flags);
|
void _ResizeHashTableIfNeeded(uint32 flags);
|
||||||
|
|
||||||
static Link* _AllocateLink(uint32 flags);
|
|
||||||
static void _FreeLink(HashedObjectCache::Link* link,
|
|
||||||
uint32 flags);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HashTable hash_table;
|
HashTable hash_table;
|
||||||
size_t lower_boundary;
|
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");
|
CREATE_PARANOIA_CHECK_SET(slab, "slab");
|
||||||
|
|
||||||
for (size_t i = 0; i < slab->size; i++) {
|
for (size_t i = 0; i < slab->size; i++) {
|
||||||
bool failedOnFirst = false;
|
status_t status = B_OK;
|
||||||
|
if (constructor)
|
||||||
status_t status = PrepareObject(slab, data, flags);
|
|
||||||
if (status < B_OK)
|
|
||||||
failedOnFirst = true;
|
|
||||||
else if (constructor)
|
|
||||||
status = constructor(cookie, data);
|
status = constructor(cookie, data);
|
||||||
|
|
||||||
if (status < B_OK) {
|
if (status != B_OK) {
|
||||||
if (!failedOnFirst)
|
|
||||||
UnprepareObject(slab, data, flags);
|
|
||||||
|
|
||||||
data = ((uint8*)pages) + slab->offset;
|
data = ((uint8*)pages) + slab->offset;
|
||||||
for (size_t j = 0; j < i; j++) {
|
for (size_t j = 0; j < i; j++) {
|
||||||
if (destructor)
|
if (destructor)
|
||||||
destructor(cookie, data);
|
destructor(cookie, data);
|
||||||
UnprepareObject(slab, data, flags);
|
|
||||||
data += object_size;
|
data += object_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,25 +183,11 @@ ObjectCache::UninitSlab(slab* slab)
|
|||||||
for (size_t i = 0; i < slab->size; i++) {
|
for (size_t i = 0; i < slab->size; i++) {
|
||||||
if (destructor)
|
if (destructor)
|
||||||
destructor(cookie, data);
|
destructor(cookie, data);
|
||||||
UnprepareObject(slab, data, flags);
|
|
||||||
data += object_size;
|
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
|
void
|
||||||
ObjectCache::ReturnObjectToSlab(slab* source, void* object, uint32 flags)
|
ObjectCache::ReturnObjectToSlab(slab* source, void* object, uint32 flags)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -94,11 +94,6 @@ public:
|
|||||||
size_t byteCount, uint32 flags);
|
size_t byteCount, uint32 flags);
|
||||||
void UninitSlab(slab* slab);
|
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,
|
void ReturnObjectToSlab(slab* source, void* object,
|
||||||
uint32 flags);
|
uint32 flags);
|
||||||
|
|
||||||
@@ -127,23 +122,15 @@ object_to_link(void* object, size_t objectSize)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline slab *
|
static inline void*
|
||||||
slab_in_pages(const void *pages, size_t slab_size)
|
lower_boundary(const void* object, size_t byteCount)
|
||||||
{
|
{
|
||||||
return (slab *)(((uint8 *)pages) + slab_size - sizeof(slab));
|
return (void*)((addr_t)object & ~(byteCount - 1));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline const void *
|
|
||||||
lower_boundary(void *object, size_t byteCount)
|
|
||||||
{
|
|
||||||
const uint8 *null = (uint8 *)NULL;
|
|
||||||
return null + ((((uint8 *)object) - null) & ~(byteCount - 1));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
check_cache_quota(ObjectCache *cache)
|
check_cache_quota(ObjectCache* cache)
|
||||||
{
|
{
|
||||||
if (cache->maximum == 0)
|
if (cache->maximum == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -12,6 +12,13 @@
|
|||||||
#include "slab_private.h"
|
#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*
|
/*static*/ SmallObjectCache*
|
||||||
SmallObjectCache::Create(const char* name, size_t object_size,
|
SmallObjectCache::Create(const char* name, size_t object_size,
|
||||||
size_t alignment, size_t maximum, uint32 flags, void* cookie,
|
size_t alignment, size_t maximum, uint32 flags, void* cookie,
|
||||||
@@ -57,7 +64,11 @@ SmallObjectCache::CreateSlab(uint32 flags)
|
|||||||
|
|
||||||
void* pages;
|
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 NULL;
|
||||||
|
|
||||||
return InitSlab(slab_in_pages(pages, slab_size), pages,
|
return InitSlab(slab_in_pages(pages, slab_size), pages,
|
||||||
@@ -69,7 +80,10 @@ void
|
|||||||
SmallObjectCache::ReturnSlab(slab* slab, uint32 flags)
|
SmallObjectCache::ReturnSlab(slab* slab, uint32 flags)
|
||||||
{
|
{
|
||||||
UninitSlab(slab);
|
UninitSlab(slab);
|
||||||
|
|
||||||
|
Unlock();
|
||||||
MemoryManager::Free(slab->pages, flags);
|
MemoryManager::Free(slab->pages, flags);
|
||||||
|
Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user