From e2252c9ba74505cdd4dec1f7bfe83e8a64ab2e0d Mon Sep 17 00:00:00 2001 From: Ben Ashbaugh Date: Tue, 29 Oct 2024 19:12:23 -0700 Subject: [PATCH] extend LeakChecking to track SVM and USM allocations --- intercept/src/dispatch.cpp | 7 +++++++ intercept/src/intercept.h | 12 ++++++++++++ intercept/src/objtracker.cpp | 30 ++++++++++++++++++++++++++++++ intercept/src/objtracker.h | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+) diff --git a/intercept/src/dispatch.cpp b/intercept/src/dispatch.cpp index 5aac4194..fdf82cc7 100644 --- a/intercept/src/dispatch.cpp +++ b/intercept/src/dispatch.cpp @@ -6338,6 +6338,7 @@ CL_API_ENTRY void* CL_API_CALL CLIRN(clSVMAlloc) ( // if ErrorLogging is enabled. cl_int errorCode = ( retVal != NULL ) ? CL_SUCCESS : CL_INVALID_OPERATION; CHECK_ERROR( errorCode ); + ADD_POINTER_ALLOCATION( retVal ); CALL_LOGGING_EXIT( errorCode, "returned %p", retVal ); return retVal; @@ -6370,6 +6371,7 @@ CL_API_ENTRY void CL_API_CALL CLIRN(clSVMFree) ( HOST_PERFORMANCE_TIMING_END(); REMOVE_SVM_ALLOCATION( svm_pointer ); + ADD_POINTER_FREE( svm_pointer ); CALL_LOGGING_EXIT( CL_SUCCESS ); } } @@ -9736,6 +9738,7 @@ CL_API_ENTRY void* CL_API_CALL clHostMemAllocINTEL( ADD_USM_ALLOCATION( retVal, size ); USM_ALLOC_PROPERTIES_CLEANUP( newProperties ); CHECK_ERROR( errcode_ret[0] ); + ADD_POINTER_ALLOCATION( retVal ); CALL_LOGGING_EXIT( errcode_ret[0], "returned %p", retVal ); return retVal; @@ -9812,6 +9815,7 @@ CL_API_ENTRY void* CL_API_CALL clDeviceMemAllocINTEL( ADD_USM_ALLOCATION( retVal, size ); USM_ALLOC_PROPERTIES_CLEANUP( newProperties ); CHECK_ERROR( errcode_ret[0] ); + ADD_POINTER_ALLOCATION( retVal ); CALL_LOGGING_EXIT( errcode_ret[0], "returned %p", retVal ); return retVal; @@ -9888,6 +9892,7 @@ CL_API_ENTRY void* CL_API_CALL clSharedMemAllocINTEL( ADD_USM_ALLOCATION( retVal, size ); USM_ALLOC_PROPERTIES_CLEANUP( newProperties ); CHECK_ERROR( errcode_ret[0] ); + ADD_POINTER_ALLOCATION( retVal ); CALL_LOGGING_EXIT( errcode_ret[0], "returned %p", retVal ); return retVal; @@ -9924,6 +9929,7 @@ CL_API_ENTRY cl_int CL_API_CALL clMemFreeINTEL( HOST_PERFORMANCE_TIMING_END(); REMOVE_USM_ALLOCATION( ptr ); CHECK_ERROR( retVal ); + ADD_POINTER_FREE( ptr ); CALL_LOGGING_EXIT( retVal ); return retVal; @@ -9961,6 +9967,7 @@ clMemBlockingFreeINTEL( HOST_PERFORMANCE_TIMING_END(); REMOVE_USM_ALLOCATION( ptr ); CHECK_ERROR( retVal ); + ADD_POINTER_FREE( ptr ); CALL_LOGGING_EXIT( retVal ); DEVICE_PERFORMANCE_TIMING_CHECK(); FLUSH_CHROME_TRACE_BUFFERING(); diff --git a/intercept/src/intercept.h b/intercept/src/intercept.h index 5ac55b7a..3d83c315 100644 --- a/intercept/src/intercept.h +++ b/intercept/src/intercept.h @@ -2008,6 +2008,18 @@ inline CObjectTracker& CLIntercept::objectTracker() pIntercept->objectTracker().AddRelease(_obj); \ } +#define ADD_POINTER_ALLOCATION( _ptr ) \ + if( pIntercept->config().LeakChecking ) \ + { \ + pIntercept->objectTracker().AddPointerAllocation(_ptr); \ + } + +#define ADD_POINTER_FREE( _ptr ) \ + if( pIntercept->config().LeakChecking ) \ + { \ + pIntercept->objectTracker().AddPointerFree(_ptr); \ + } + /////////////////////////////////////////////////////////////////////////////// // #define LOG_CLINFO() \ diff --git a/intercept/src/objtracker.cpp b/intercept/src/objtracker.cpp index 038ca9a4..0a15e2c8 100644 --- a/intercept/src/objtracker.cpp +++ b/intercept/src/objtracker.cpp @@ -42,6 +42,35 @@ void CObjectTracker::ReportHelper( } } +void CObjectTracker::ReportHelper( + const std::string& label, + const CObjectTracker::CPointerTracker& tracker, + std::ostream& os ) +{ + size_t numAllocations = tracker.NumAllocations.load(std::memory_order_relaxed); + size_t numFrees = tracker.NumFrees.load(std::memory_order_relaxed); + + if( numFrees < numAllocations ) + { + os << "Possible leak of type " << label << "!" << std::endl; + os << " Number of Allocations: " << numAllocations << std::endl; + os << " Number of Frees: " << numFrees << std::endl; + } + else if( numFrees > numAllocations ) + { + // If there are more frees than allocations then this is an unexpected + // situation. It usually means that some allocations aren't tracked + // correctly, or that a free returned an error. + os << "Unexpected counts for type " << label << "!" << std::endl; + os << " Number of Allocations: " << numAllocations << std::endl; + os << " Number of Frees: " << numFrees << std::endl; + } + else if( numAllocations ) + { + os << "No " << label << " leaks detected." << std::endl; + } +} + void CObjectTracker::writeReport( std::ostream& os ) { os << std::endl; @@ -55,4 +84,5 @@ void CObjectTracker::writeReport( std::ostream& os ) ReportHelper( "cl_event", m_Events, os ); ReportHelper( "cl_semaphore_khr", m_Semaphores, os ); ReportHelper( "cl_command_buffer_khr", m_CommandBuffers, os ); + ReportHelper( "SVM/USM allocation", m_Pointers, os ); } diff --git a/intercept/src/objtracker.h b/intercept/src/objtracker.h index e58b4988..be733d16 100644 --- a/intercept/src/objtracker.h +++ b/intercept/src/objtracker.h @@ -44,6 +44,22 @@ class CObjectTracker } } + void AddPointerAllocation( const void* ptr ) + { + if( ptr ) + { + m_Pointers.NumAllocations.fetch_add(1, std::memory_order_relaxed); + } + } + + void AddPointerFree( const void* ptr ) + { + if( ptr ) + { + m_Pointers.NumFrees.fetch_add(1, std::memory_order_relaxed); + } + } + private: struct CTracker { @@ -57,6 +73,16 @@ class CObjectTracker std::atomic NumReleases; }; + struct CPointerTracker + { + CPointerTracker() : + NumAllocations(0), + NumFrees(0) {}; + + std::atomic NumAllocations; + std::atomic NumFrees; + }; + CTracker m_Devices; CTracker m_Contexts; CTracker m_CommandQueues; @@ -80,10 +106,16 @@ class CObjectTracker CTracker& GetTracker( cl_semaphore_khr ) { return m_Semaphores; } CTracker& GetTracker( cl_command_buffer_khr ) { return m_CommandBuffers; } + CPointerTracker m_Pointers; + static void ReportHelper( const std::string& label, const CTracker& tracker, std::ostream& os ); + static void ReportHelper( + const std::string& label, + const CPointerTracker& tracker, + std::ostream& os ); DISALLOW_COPY_AND_ASSIGN( CObjectTracker ); };