From 2be0b7cc432eee1cb0c2a5e2edf5e85a6eb5687d Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Sun, 27 Apr 2008 03:22:26 +0000 Subject: [PATCH] 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 --- src/system/kernel/slab/Slab.cpp | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/system/kernel/slab/Slab.cpp b/src/system/kernel/slab/Slab.cpp index b1c7dd47a0..7f390ac7eb 100644 --- a/src/system/kernel/slab/Slab.cpp +++ b/src/system/kernel/slab/Slab.cpp @@ -39,6 +39,11 @@ #define TRACE_CACHE(cache, format, bananas...) do { } while (0) #endif +#define OBJECT_CACHE_PARANOIA 1 +#define ENABLE_PARANOIA_CHECK_COMPONENT OBJECT_CACHE_PARANOIA +#include + + #define CACHE_ALIGN_ON_SIZE (30 << 1) static const int kMagazineCapacity = 32; @@ -173,9 +178,9 @@ static depot_magazine *alloc_magazine(); static void free_magazine(depot_magazine *magazine); - #ifdef OBJECT_CACHE_TRACING + namespace ObjectCacheTracing { class ObjectCacheTraceEntry : public AbstractTraceEntry { @@ -832,10 +837,14 @@ object_cache_alloc(object_cache *cache, uint32 flags) source = cache->partial.Head(); } + ParanoiaChecker _2(source); + object_link *link = _pop(source->free); source->count--; cache->used_count++; + REMOVE_PARANOIA_CHECK(source, &link->next, sizeof(void*)); + TRACE_CACHE(cache, "allocate %p (%p) from %p, %lu remaining.", 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) panic("object_cache: free'd object has no slab"); + ParanoiaChecker _(source); + object_link *link = object_to_link(object, cache->object_size); 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++; cache->used_count--; + ADD_PARANOIA_CHECK(source, &link->next, sizeof(void*)); + if (source->count == source->size) { cache->partial.Remove(source); @@ -957,6 +970,8 @@ object_cache::InitSlab(slab *slab, void *pages, size_t byteCount) uint8 *data = ((uint8 *)pages) + slab->offset; + CREATE_PARANOIA_CHECK_SET(slab, "slab"); + for (size_t i = 0; i < slab->size; i++) { bool failedOnFirst = false; @@ -978,10 +993,16 @@ object_cache::InitSlab(slab *slab, void *pages, size_t byteCount) data += object_size; } + DELETE_PARANOIA_CHECK_SET(slab); + return NULL; } _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; } @@ -997,6 +1018,8 @@ object_cache::UninitSlab(slab *slab) if (slab->count != slab->size) panic("cache: destroying a slab which isn't empty."); + DELETE_PARANOIA_CHECK_SET(slab); + uint8 *data = ((uint8 *)slab->pages) + slab->offset; for (size_t i = 0; i < slab->size; i++) {