Author: bonefish Date: 2011-11-01 20:40:27 +0100 (Tue, 01 Nov 2011) New Revision: 43078 Changeset: https://dev.haiku-os.org/changeset/43078 Modified: haiku/trunk/src/system/kernel/slab/MemoryManager.cpp haiku/trunk/src/system/kernel/slab/MemoryManager.h haiku/trunk/src/system/kernel/slab/Slab.cpp haiku/trunk/src/system/kernel/slab/slab_debug.h Log: mmlr + bonefish: * dump_allocations_per_caller(): Compute the total allocation count and size from the caller infos instead of using return arguments in the helper functions called. * Move caller info update code from analyze_allocation_callers() to new function slab_debug_add_allocation_for_caller(), so it can be reused. * Add MemoryManager::AnalyzeAllocationCallers() to collect the allocation information for the memory manager. Modified: haiku/trunk/src/system/kernel/slab/MemoryManager.cpp =================================================================== --- haiku/trunk/src/system/kernel/slab/MemoryManager.cpp 2011-11-01 19:25:40 UTC (rev 43077) +++ haiku/trunk/src/system/kernel/slab/MemoryManager.cpp 2011-11-01 19:40:27 UTC (rev 43078) @@ -22,7 +22,6 @@ #include "kernel_debug_config.h" #include "ObjectCache.h" -#include "slab_debug.h" #include "slab_private.h" @@ -867,6 +866,44 @@ } +#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING + +/*static*/ bool +MemoryManager::AnalyzeAllocationCallers() +{ + for (AreaTable::Iterator it = sAreaTable.GetIterator(); + Area* area = it.Next();) { + for (int32 i = 0; i < SLAB_META_CHUNKS_PER_AREA; i++) { + MetaChunk* metaChunk = area->metaChunks + i; + if (metaChunk->chunkSize == 0) + continue; + + for (uint32 k = 0; k < metaChunk->chunkCount; k++) { + Chunk* chunk = metaChunk->chunks + k; + + // skip free chunks + if (_IsChunkFree(metaChunk, chunk)) + continue; + + addr_t reference = chunk->reference; + if ((reference & 1) == 0 || reference == 1) + continue; + + addr_t chunkAddress = _ChunkAddress(metaChunk, chunk); + size_t size = reference - chunkAddress + 1; + + slab_debug_add_allocation_for_caller( + _TrackingInfoFor((void*)chunkAddress, size), size); + } + } + } + + return true; +} + +#endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING + + /*static*/ status_t MemoryManager::_AllocateChunks(size_t chunkSize, uint32 chunkCount, uint32 flags, MetaChunk*& _metaChunk, Chunk*& _chunk) @@ -1989,9 +2026,7 @@ MemoryManager::_AddTrackingInfo(void* allocation, size_t size, AbstractTraceEntryWithStackTrace* traceEntry) { - AllocationTrackingInfo* info = (AllocationTrackingInfo*) - ((uint8*)allocation + size - sizeof(AllocationTrackingInfo)); - info->Init(traceEntry); + _TrackingInfoFor(allocation, size)->Init(traceEntry); } #endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING Modified: haiku/trunk/src/system/kernel/slab/MemoryManager.h =================================================================== --- haiku/trunk/src/system/kernel/slab/MemoryManager.h 2011-11-01 19:25:40 UTC (rev 43077) +++ haiku/trunk/src/system/kernel/slab/MemoryManager.h 2011-11-01 19:40:27 UTC (rev 43078) @@ -14,8 +14,7 @@ #include <util/DoublyLinkedList.h> #include <util/OpenHashTable.h> -#include "kernel_debug_config.h" -#include "tracing_config.h" +#include "slab_debug.h" class AbstractTraceEntryWithStackTrace; @@ -61,6 +60,8 @@ static bool MaintenanceNeeded(); static void PerformMaintenance(); + static bool AnalyzeAllocationCallers(); + private: struct Tracing; @@ -195,9 +196,11 @@ static int _DumpArea(int argc, char** argv); static int _DumpAreas(int argc, char** argv); -#if SLAB_ALLOCATION_TRACKING && SLAB_MEMORY_MANAGER_TRACING +#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING static void _AddTrackingInfo(void* allocation, size_t size, AbstractTraceEntryWithStackTrace* entry); + static AllocationTrackingInfo* _TrackingInfoFor(void* allocation, + size_t size); #endif private: @@ -273,4 +276,16 @@ } +#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING + +/*static*/ inline AllocationTrackingInfo* +MemoryManager::_TrackingInfoFor(void* allocation, size_t size) +{ + return (AllocationTrackingInfo*)((uint8*)allocation + size + - sizeof(AllocationTrackingInfo)); +} + +#endif // SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING + + #endif // MEMORY_MANAGER_H Modified: haiku/trunk/src/system/kernel/slab/Slab.cpp =================================================================== --- haiku/trunk/src/system/kernel/slab/Slab.cpp 2011-11-01 19:25:40 UTC (rev 43077) +++ haiku/trunk/src/system/kernel/slab/Slab.cpp 2011-11-01 19:40:27 UTC (rev 43078) @@ -329,9 +329,6 @@ #if SLAB_ALLOCATION_TRACKING_AVAILABLE -#if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING - // until memory manager tracking is analyzed - static caller_info* get_caller_info(addr_t caller) { @@ -353,9 +350,7 @@ return info; } -#endif // SLAB_OBJECT_CACHE_ALLOCATION_TRACKING - static int caller_info_compare_size(const void* _a, const void* _b) { @@ -374,39 +369,47 @@ } +bool +slab_debug_add_allocation_for_caller(const AllocationTrackingInfo* info, + size_t allocationSize) +{ + if (!info->IsInitialized()) + return true; + + addr_t caller = 0; + AbstractTraceEntryWithStackTrace* traceEntry = info->TraceEntry(); + + if (traceEntry != NULL && info->IsTraceEntryValid()) { + caller = tracing_find_caller_in_stack_trace( + traceEntry->StackTrace(), kSlabCodeAddressRanges, + kSlabCodeAddressRangeCount); + } + + caller_info* callerInfo = get_caller_info(caller); + if (callerInfo == NULL) { + kprintf("out of space for caller infos\n"); + return false; + } + + callerInfo->count++; + callerInfo->size += allocationSize; + + return true; +} + + #if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING static bool -analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList, - size_t& _totalAllocationSize, size_t& _totalAllocationCount) +analyze_allocation_callers(ObjectCache* cache, const SlabList& slabList) { for (SlabList::ConstIterator it = slabList.GetIterator(); slab* slab = it.Next();) { for (uint32 i = 0; i < slab->size; i++) { - AllocationTrackingInfo* info = &slab->tracking[i]; - if (!info->IsInitialized()) - continue; - - _totalAllocationSize += cache->object_size; - _totalAllocationCount++; - - addr_t caller = 0; - AbstractTraceEntryWithStackTrace* traceEntry = info->TraceEntry(); - - if (traceEntry != NULL && info->IsTraceEntryValid()) { - caller = tracing_find_caller_in_stack_trace( - traceEntry->StackTrace(), kSlabCodeAddressRanges, - kSlabCodeAddressRangeCount); - } - - caller_info* callerInfo = get_caller_info(caller); - if (callerInfo == NULL) { - kprintf("out of space for caller infos\n"); + if (!slab_debug_add_allocation_for_caller(&slab->tracking[i], + cache->object_size)) { return false; } - - callerInfo->count++; - callerInfo->size += cache->object_size; } } @@ -415,13 +418,10 @@ static bool -analyze_allocation_callers(ObjectCache* cache, size_t& _totalAllocationSize, - size_t& _totalAllocationCount) +analyze_allocation_callers(ObjectCache* cache) { - return analyze_allocation_callers(cache, cache->full, _totalAllocationSize, - _totalAllocationCount) - && analyze_allocation_callers(cache, cache->partial, - _totalAllocationSize, _totalAllocationCount); + return analyze_allocation_callers(cache, cache->full) + && analyze_allocation_callers(cache, cache->partial); } #endif // SLAB_OBJECT_CACHE_ALLOCATION_TRACKING @@ -453,12 +453,10 @@ sCallerInfoCount = 0; - size_t totalAllocationSize = 0; - size_t totalAllocationCount = 0; if (cache != NULL) { #if SLAB_OBJECT_CACHE_ALLOCATION_TRACKING - analyze_allocation_callers(cache, totalAllocationSize, - totalAllocationCount); + if (!analyze_allocation_callers(cache)) + return 0; #else kprintf("Object cache allocation tracking not available. " "SLAB_OBJECT_CACHE_TRACING (%d) and " @@ -471,10 +469,15 @@ ObjectCacheList::Iterator it = sObjectCaches.GetIterator(); while (it.HasNext()) { - analyze_allocation_callers(it.Next(), totalAllocationSize, - totalAllocationCount); + if (!analyze_allocation_callers(it.Next())) + return 0; } #endif + +#if SLAB_MEMORY_MANAGER_ALLOCATION_TRACKING + if (!MemoryManager::AnalyzeAllocationCallers()) + return 0; +#endif } // sort the array @@ -484,6 +487,9 @@ kprintf("%ld different callers, sorted by %s...\n\n", sCallerInfoCount, sortBySize ? "size" : "count"); + size_t totalAllocationSize = 0; + size_t totalAllocationCount = 0; + kprintf(" count size caller\n"); kprintf("----------------------------------\n"); for (int32 i = 0; i < sCallerInfoCount; i++) { @@ -503,6 +509,9 @@ exactMatch ? "" : " (nearest)"); } else kprintf("\n"); + + totalAllocationCount += info.count; + totalAllocationSize += info.size; } kprintf("\ntotal allocations: %" B_PRIuSIZE ", %" B_PRIuSIZE " bytes\n", Modified: haiku/trunk/src/system/kernel/slab/slab_debug.h =================================================================== --- haiku/trunk/src/system/kernel/slab/slab_debug.h 2011-11-01 19:25:40 UTC (rev 43077) +++ haiku/trunk/src/system/kernel/slab/slab_debug.h 2011-11-01 19:40:27 UTC (rev 43078) @@ -47,11 +47,6 @@ struct object_depot; -void dump_object_depot(object_depot* depot); -int dump_object_depot(int argCount, char** args); -int dump_depot_magazine(int argCount, char** args); - - #if SLAB_ALLOCATION_TRACKING_AVAILABLE class AllocationTrackingInfo { @@ -94,6 +89,14 @@ #endif // SLAB_ALLOCATION_TRACKING_AVAILABLE +void dump_object_depot(object_depot* depot); +int dump_object_depot(int argCount, char** args); +int dump_depot_magazine(int argCount, char** args); + +bool slab_debug_add_allocation_for_caller( + const AllocationTrackingInfo* info, size_t allocationSize); + + #if PARANOID_KERNEL_MALLOC || PARANOID_KERNEL_FREE static inline void* fill_block(void* buffer, size_t size, uint32 pattern)