Added paranoia checks. They reveal that a net buffer data node is freed
twice when running the OpenSSH "forwarding" test, which corrupts the slab's object list. It's not quite clear to me yet why that happens. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25208 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -39,6 +39,11 @@
|
|||||||
#define TRACE_CACHE(cache, format, bananas...) do { } while (0)
|
#define TRACE_CACHE(cache, format, bananas...) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define OBJECT_CACHE_PARANOIA 1
|
||||||
|
#define ENABLE_PARANOIA_CHECK_COMPONENT OBJECT_CACHE_PARANOIA
|
||||||
|
#include <debug_paranoia.h>
|
||||||
|
|
||||||
|
|
||||||
#define CACHE_ALIGN_ON_SIZE (30 << 1)
|
#define CACHE_ALIGN_ON_SIZE (30 << 1)
|
||||||
|
|
||||||
static const int kMagazineCapacity = 32;
|
static const int kMagazineCapacity = 32;
|
||||||
@@ -173,9 +178,9 @@ static depot_magazine *alloc_magazine();
|
|||||||
static void free_magazine(depot_magazine *magazine);
|
static void free_magazine(depot_magazine *magazine);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef OBJECT_CACHE_TRACING
|
#ifdef OBJECT_CACHE_TRACING
|
||||||
|
|
||||||
|
|
||||||
namespace ObjectCacheTracing {
|
namespace ObjectCacheTracing {
|
||||||
|
|
||||||
class ObjectCacheTraceEntry : public AbstractTraceEntry {
|
class ObjectCacheTraceEntry : public AbstractTraceEntry {
|
||||||
@@ -832,10 +837,14 @@ object_cache_alloc(object_cache *cache, uint32 flags)
|
|||||||
source = cache->partial.Head();
|
source = cache->partial.Head();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParanoiaChecker _2(source);
|
||||||
|
|
||||||
object_link *link = _pop(source->free);
|
object_link *link = _pop(source->free);
|
||||||
source->count--;
|
source->count--;
|
||||||
cache->used_count++;
|
cache->used_count++;
|
||||||
|
|
||||||
|
REMOVE_PARANOIA_CHECK(source, &link->next, sizeof(void*));
|
||||||
|
|
||||||
TRACE_CACHE(cache, "allocate %p (%p) from %p, %lu remaining.",
|
TRACE_CACHE(cache, "allocate %p (%p) from %p, %lu remaining.",
|
||||||
link_to_object(link, cache->object_size), link, source, source->count);
|
link_to_object(link, cache->object_size), link, source, source->count);
|
||||||
|
|
||||||
@@ -856,6 +865,8 @@ object_cache_return_to_slab(object_cache *cache, slab *source, void *object)
|
|||||||
if (source == NULL)
|
if (source == NULL)
|
||||||
panic("object_cache: free'd object has no slab");
|
panic("object_cache: free'd object has no slab");
|
||||||
|
|
||||||
|
ParanoiaChecker _(source);
|
||||||
|
|
||||||
object_link *link = object_to_link(object, cache->object_size);
|
object_link *link = object_to_link(object, cache->object_size);
|
||||||
|
|
||||||
TRACE_CACHE(cache, "returning %p (%p) to %p, %lu used (%lu empty slabs).",
|
TRACE_CACHE(cache, "returning %p (%p) to %p, %lu used (%lu empty slabs).",
|
||||||
@@ -866,6 +877,8 @@ object_cache_return_to_slab(object_cache *cache, slab *source, void *object)
|
|||||||
source->count++;
|
source->count++;
|
||||||
cache->used_count--;
|
cache->used_count--;
|
||||||
|
|
||||||
|
ADD_PARANOIA_CHECK(source, &link->next, sizeof(void*));
|
||||||
|
|
||||||
if (source->count == source->size) {
|
if (source->count == source->size) {
|
||||||
cache->partial.Remove(source);
|
cache->partial.Remove(source);
|
||||||
|
|
||||||
@@ -957,6 +970,8 @@ object_cache::InitSlab(slab *slab, void *pages, size_t byteCount)
|
|||||||
|
|
||||||
uint8 *data = ((uint8 *)pages) + slab->offset;
|
uint8 *data = ((uint8 *)pages) + slab->offset;
|
||||||
|
|
||||||
|
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;
|
bool failedOnFirst = false;
|
||||||
|
|
||||||
@@ -978,10 +993,16 @@ object_cache::InitSlab(slab *slab, void *pages, size_t byteCount)
|
|||||||
data += object_size;
|
data += object_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DELETE_PARANOIA_CHECK_SET(slab);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
_push(slab->free, object_to_link(data, object_size));
|
_push(slab->free, object_to_link(data, object_size));
|
||||||
|
|
||||||
|
ADD_PARANOIA_CHECK(slab, &object_to_link(data, object_size)->next,
|
||||||
|
sizeof(void*));
|
||||||
|
|
||||||
data += object_size;
|
data += object_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -997,6 +1018,8 @@ object_cache::UninitSlab(slab *slab)
|
|||||||
if (slab->count != slab->size)
|
if (slab->count != slab->size)
|
||||||
panic("cache: destroying a slab which isn't empty.");
|
panic("cache: destroying a slab which isn't empty.");
|
||||||
|
|
||||||
|
DELETE_PARANOIA_CHECK_SET(slab);
|
||||||
|
|
||||||
uint8 *data = ((uint8 *)slab->pages) + slab->offset;
|
uint8 *data = ((uint8 *)slab->pages) + slab->offset;
|
||||||
|
|
||||||
for (size_t i = 0; i < slab->size; i++) {
|
for (size_t i = 0; i < slab->size; i++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user