memana/analyzetoolclient/dynamicmemoryhook/src/analyzetoolallocator.cpp
changeset 0 f0f2b8682603
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/memana/analyzetoolclient/dynamicmemoryhook/src/analyzetoolallocator.cpp	Thu Feb 11 15:51:35 2010 +0200
@@ -0,0 +1,1008 @@
+/*
+* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Definitions for the class RAnalyzeToolAllocator.
+*
+*/
+
+
+#include "analyzetoolallocator.h"
+#include "analyzetoolmemoryallocator.h"
+#include "atlog.h"
+#include "analyzetoolpanics.pan"
+#include "analyzetoolfastlog.h"
+#include <e32svr.h>
+
+// CONSTANTS
+
+// Length of the callstack address
+const TUint32 KAddressLength = 4;
+
+// Thread count
+const TInt KThreadCount = 1;
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::RAnalyzeToolAllocator()
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+RAnalyzeToolAllocator::RAnalyzeToolAllocator( TBool aNotFirst, 
+                                              RATStorageServer& aStorageServer, 
+                                              RArray<TCodeblock>& aCodeblocks, 
+                                              RMutex& aMutex,
+                                              TUint aProcessId,
+                                              RAnalyzeTool& aAnalyzeTool,
+                                              TBool aStorageServerOpen,
+                                              TUint32 aLogOption,
+                                              TUint32 aAllocCallStackSize,
+                                              TUint32 aFreeCallStackSize ) :
+    RAnalyzeToolMemoryAllocator( aNotFirst ),
+    iStorageServer( aStorageServer ), 
+    iCodeblocks( aCodeblocks ), 
+    iMutex( aMutex ),
+    iProcessId( aProcessId ),
+    iThreadArray( KATMaxCallstackLength ),
+    iAnalyzeTool( aAnalyzeTool ),
+    iStorageServerOpen( aStorageServerOpen ),
+    iLogOption( aLogOption ),
+    iAllocMaxCallStack( aAllocCallStackSize ),
+    iFreeMaxCallStack( aFreeCallStackSize )
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::RAnalyzeToolAllocator()" );
+    
+    // Append thread to array of the users of this allocator
+    TThreadParamsBuf params;
+    params().iThreadId = RThread().Id().operator TUint();
+    TInt error = iAnalyzeTool.ThreadStack( params );
+    if ( KErrNone == error )
+        {
+        LOGSTR2( "ATMH Thread stack address: %x", params().iStackAddress );
+        LOGSTR2( "ATMH Thread stack size:    %x", params().iStackSize );
+        error = iThreadArray.Append( TThreadStack( RThread().Id(), 
+                             params().iStackAddress + params().iStackSize ) );
+        }
+    
+    __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantAppendToTheArray ) ); 
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::~RAnalyzeToolAllocator()
+// Destructor.
+// -----------------------------------------------------------------------------
+//
+RAnalyzeToolAllocator::~RAnalyzeToolAllocator()
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::~RAnalyzeToolAllocator()" );
+    
+    // Close the thread array 
+    iThreadArray.Close();
+    }
+    
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Uninstall()
+// Uninstalls the current allocator
+// -----------------------------------------------------------------------------
+//
+void RAnalyzeToolAllocator::Uninstall()
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Uninstall()" );
+
+    // Switch back to the original allocator
+    SwitchOriginalAllocator();
+    
+    // Check if this is shared allocator between threads
+    if ( iThreadArray.Count() > KThreadCount )
+        {
+        // Close the shared allocator
+        Close();
+        return;
+        }
+
+#if ( SYMBIAN_VERSION_SUPPORT >= SYMBIAN_3 )
+    #ifndef __WINS__ 
+    // Remove dummy Tls handle
+    UserSvr::DllFreeTls( KDummyHandle );
+    #endif
+#endif
+    
+    // Since this is the last thread using this allocator it can be deleted
+    delete this;
+    }
+
+#ifdef __WINS__
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Alloc() WINS version
+// Allocates a cell of specified size from the heap.
+// -----------------------------------------------------------------------------
+//
+UEXPORT_C TAny* RAnalyzeToolAllocator::Alloc( TInt aSize )
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc()" );
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Alloc memory from the original allocator
+    TAny* p = iAllocator->Alloc( aSize );
+    
+    LOGSTR3( "ATMH RAnalyzeToolAllocator::Alloc() - aSize: %i, address: %x", 
+             aSize,  (TUint32) p );
+    
+    // Don't collect call stack and log data
+    // if storage server not open or logging mode not fast xti.
+    if ( iStorageServerOpen || iLogOption == EATLogToXtiFast )
+        {
+        // Reset the callstack
+        iCallStack.Reset();
+    
+        // Find the current thread callstack start address
+        TUint32 stackstart( 0 );
+        TBool found( FindCurrentThreadStack( stackstart ) );
+        LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found );
+        
+        TUint32 _sp;
+        __asm
+            {
+            mov [_sp], esp
+            }
+        
+        // Get codeblocks count
+        TInt blocksCount( iCodeblocks.Count() );
+        TInt error( KErrNone );
+        TUint arrayCounter = 0;
+        
+        for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348
+            {
+            TUint32 addr = (TUint32) *( (TUint32*) i );
+            if ( ! IsAddressLoadedCode( addr ) )
+                continue;
+            for ( TInt j = 0; j < blocksCount; j++ )
+                {
+                if ( iCodeblocks[j].CheckAddress( addr ) )
+                    {
+                    // To avoid recursive call to ReAlloc specifying granularity
+                    // Add address to the callstack
+                    iCallStack[arrayCounter] = addr;
+                    arrayCounter++;
+                    break;
+                    }
+                }
+            if ( arrayCounter == KATMaxCallstackLength ||
+                 arrayCounter == iAllocMaxCallStack )
+                {
+                LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter );
+                break;
+                }
+            }
+        // Log the memory allocation information
+        if ( iLogOption == EATLogToXtiFast )
+            {
+            // Using fast xti.
+            ATFastLogMemoryAllocated( iProcessId, (TUint32) p, iCallStack, aSize );
+            }
+        else
+            {
+            // Using storage server.
+            error = iStorageServer.LogMemoryAllocated( (TUint32) p,
+                                                       iCallStack,
+                                                       aSize );
+            if ( KErrNone != error )
+                {
+                LOGSTR2( "ATMH LogMemoryAllocated error %i", error );
+                switch ( error )
+                    {
+                    case KErrNoMemory:
+                    LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - KErrNoMemory case"  );
+                    if ( iStorageServerOpen )
+                        {
+                        iStorageServerOpen = EFalse;
+                        LOGSTR1( "ATMH RAnalyzeToolMainAllocator::Alloc() - close iStorageServer"  );
+                        iStorageServer.Close();
+                        }
+                    break;
+                    }
+                }
+            }
+        }
+    // Release the mutex
+    iMutex.Signal();
+    
+    return p;
+    }
+#else
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Alloc() ARMV5 version
+// Allocates a cell of specified size from the heap.
+// -----------------------------------------------------------------------------
+//
+TAny* RAnalyzeToolAllocator::Alloc( TInt aSize )
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc()" );
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Alloc memory from the original allocator
+    TAny* p = iAllocator->Alloc( aSize );
+    
+    // Don't collect call stack and log data
+    // if storage server not open or logging mode not fast xti.
+    if ( iStorageServerOpen || iLogOption == EATLogToXtiFast )
+        {
+        // Reset the callstack
+        iCallStack.Reset(); 
+        
+        // Find the current thread callstack start address
+        TUint32 stackstart( 0 );
+        TBool found( FindCurrentThreadStack( stackstart ) );
+        LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found );
+        
+        // Get codeblocks count
+        TInt blocksCount( iCodeblocks.Count() );
+        TInt error( KErrNone );
+        TUint arrayCounter = 0;
+        
+        for ( TUint32 i = __current_sp(); i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348
+            {
+            for ( TInt j = 0; j < blocksCount; j++ )
+                {
+                if ( iCodeblocks[j].CheckAddress( (TUint32) *( (TUint32*) i ) ) )
+                    {
+                    // To avoid recursive call to ReAlloc specifying granularity
+                    // Add address to the callstack
+                    iCallStack[arrayCounter] = ( (TUint32) *( (TUint32*) i ) );
+                    arrayCounter++;
+                    break;
+                    }
+                }
+            if ( arrayCounter == KATMaxCallstackLength ||
+                 arrayCounter == iAllocMaxCallStack )
+                {
+                LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter );
+                break;
+                }
+            }
+        // Log the memory allocation information
+        if ( iLogOption == EATLogToXtiFast )
+            {
+            // Fast xti.
+            ATFastLogMemoryAllocated( iProcessId, (TUint32) p, iCallStack, aSize );
+            }
+        else
+            {
+            // Using storage server.
+            error = iStorageServer.LogMemoryAllocated( (TUint32) p, 
+                                                        iCallStack, 
+                                                        aSize );
+            if ( KErrNone != error )
+                {
+                LOGSTR2( "ATMH LogMemoryAllocated error %i", error );
+                switch ( error )
+                    {
+                    case KErrNoMemory:
+                    LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc() - KErrNoMemory case"  );
+                    if ( iStorageServerOpen )
+                        {
+                        iStorageServerOpen = EFalse;
+                        LOGSTR1( "ATMH RAnalyzeToolAllocator::Alloc() - close iStorageServer"  );
+                        iStorageServer.Close();
+                        }
+                    break;
+                    }
+                }
+            }
+        }
+ 
+    // Release the mutex
+    iMutex.Signal(); 
+    
+    // Return the allocatated memory
+    return p;
+    }
+#endif // __WINS__
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Free()
+// Frees the allocated memory
+// -----------------------------------------------------------------------------
+//
+TAny RAnalyzeToolAllocator::Free( TAny* aPtr )
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Free()" );
+
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Don't collect or log data if storage server not open or logging mode not fast xti.
+    if ( iStorageServerOpen || iLogOption == EATLogToXtiFast )
+        {
+        // Reset the callstack
+        iFreeCallStack.Reset();
+        
+        // Check if XTI logging mode because free call stack is not used in other log options.
+        if ( (iLogOption == EATUseDefault || iLogOption == EATLogToXti || iLogOption == EATLogToXtiFast )
+                && iFreeMaxCallStack > 0 )
+            {
+            // Find the current thread callstack start address
+            TUint32 stackstart( 0 );
+            TBool found( FindCurrentThreadStack( stackstart ) );
+            LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found );
+            TUint32 _sp;
+            
+            #ifdef __WINS__
+                __asm
+                    {
+                    mov [_sp], esp
+                    }
+            #else
+                _sp = __current_sp();
+            #endif
+            
+            // Get codeblocks count
+            TInt blocksCount( iCodeblocks.Count() );
+            TUint arrayCounter = 0;
+        
+            for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348
+                {
+                TUint32 addr = (TUint32) *( (TUint32*) i );
+                if ( ! IsAddressLoadedCode( addr ) )
+                    continue;
+                for ( TInt j = 0; j < blocksCount; j++ )
+                    {
+                    if ( iCodeblocks[j].CheckAddress( addr ) )
+                        {
+                        // To avoid recursive call to ReAlloc specifying granularity
+                        // Add address to the callstack
+                        iFreeCallStack[arrayCounter] = addr;
+                        arrayCounter++;
+                        break;
+                        }
+                    }
+                if ( arrayCounter == KATMaxFreeCallstackLength ||
+                     arrayCounter == iFreeMaxCallStack )
+                    {
+                    break;
+                    }
+                }
+            LOGSTR2( "ATMH > iFreeCallStack count ( %i )", arrayCounter );
+            }
+        
+        // Log freed memory.
+        if ( iLogOption == EATLogToXtiFast )
+            {
+            // Using fast xti.
+            ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack );
+            }
+        else
+            {
+            // Using storage server.
+            TInt err( iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack ) );
+            if ( err != KErrNone )
+                {
+                LOGSTR2( "ATMH > LogMemoryFreed err( %i )", err );
+                }
+            }
+        }
+    
+    // Free the memory using original allocator
+    iAllocator->Free( aPtr ); 
+    
+    LOGSTR2( "ATMH RAnalyzeToolAllocator::Free() - aPtr: %x", (TUint32)aPtr );
+    
+    // Release the mutex
+    iMutex.Signal();
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Open()
+// Opens this heap for shared access. Opening the heap increases 
+// the heap's access count by one.
+// -----------------------------------------------------------------------------
+//
+TInt RAnalyzeToolAllocator::Open()
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Open()");
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Share the memory using original allocator
+    TInt error = iAllocator->Open();
+    
+    // If everything is OK add thread to the array which use this allocator
+    if ( KErrNone == error )
+        {
+        TThreadParamsBuf params;
+        params().iThreadId = RThread().Id().operator TUint();
+        error = iAnalyzeTool.ThreadStack( params );
+
+        __ASSERT_ALWAYS( KErrNone == error, AssertPanic( ECantAppendToTheArray ) );
+
+        if ( KErrNone == error )
+            {
+            LOGSTR2( "ATMH Thread stack address: %x", params().iStackAddress );
+            LOGSTR2( "ATMH Thread stack size:    %x", params().iStackSize );
+            iThreadArray.Append( TThreadStack( RThread().Id(), 
+                    params().iStackAddress + params().iStackSize ) );
+            }
+        }
+    
+    // Release the mutex
+    iMutex.Signal();
+    
+    // Return the error code
+    return error;
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Close()
+// Closes this shared heap. Closing the heap decreases the heap's 
+// access count by one.
+// -----------------------------------------------------------------------------
+//
+void RAnalyzeToolAllocator::Close()
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Close()" );
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Close the memory using original allocator
+    iAllocator->Close();
+    
+    TInt count = iThreadArray.Count();
+    
+    // Iterate through array of threads to remove current thread
+    for ( TInt i = 0; i < count; i++ )
+        {
+        // Check if this is current thread
+        if ( iThreadArray[ i ].Match() )
+            {
+            // Remove the thread
+            iThreadArray.Remove( i );
+            break;
+            }
+        }
+    
+    // Release the mutex
+    iMutex.Signal();
+    }
+
+#ifdef __WINS__
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::ReAlloc()
+// Increases or decreases the size of an existing cell.
+// -----------------------------------------------------------------------------
+//
+TAny* RAnalyzeToolAllocator::ReAlloc( TAny* aPtr, TInt aSize, TInt aMode )
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc()" );
+
+    // Acquire the mutex
+    iMutex.Wait();
+
+    // Realloc the memory using original allocator
+    TAny* ptr = iAllocator->ReAlloc( aPtr, aSize, aMode );
+    
+    // NULL addresses are not in a process under test
+    if ( ptr && !( aMode & ENeverMove ) )
+        {
+        LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aPtr: %x, ptr: %x", 
+                (TUint32)aPtr, (TUint32)ptr );
+        LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aSize: %i, aMode: %i", 
+                aSize, aMode );
+
+        // Don't collect or log data if storage server not open or logging mode fast xti.
+        if ( iStorageServerOpen || iLogOption == EATLogToXtiFast )
+            {
+            // Reset the callstack
+            iReCallStack.Reset(); 
+
+            // Find the current thread callstack start address
+            TUint32 stackstart( 0 ); 
+            TBool found( FindCurrentThreadStack( stackstart ) );
+            LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found );
+            
+            // Get current sp
+            TUint32 _sp( 0 );
+            __asm
+                {
+                mov [_sp], esp
+                }
+            
+            // Get codeblocks count
+            TInt blocksCount( iCodeblocks.Count() );
+            TInt error( KErrNone );
+            TUint arrayCounter = 0;
+            
+            for ( TUint32 i = _sp; i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348
+                {
+                TUint32 addr = (TUint32) *( (TUint32*) i );
+                if ( ! IsAddressLoadedCode( addr ) )
+                    continue;
+                for ( TInt j = 0; j < blocksCount; j++ )
+                    {
+                    if ( iCodeblocks[j].CheckAddress( addr ) )
+                        {
+                        // To avoid recursive call to ReAlloc specifying granularity
+                        // Add address to the callstack
+                        iReCallStack[arrayCounter] = addr;
+                        arrayCounter++;
+                        break;
+                        }
+                    }
+                if ( arrayCounter == KATMaxCallstackLength || 
+                     arrayCounter == iAllocMaxCallStack )
+                    {
+                    LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter );
+                    break;
+                    }
+                }
+            
+            // No need to report free if the aPtr was NULL
+            if ( aPtr != NULL )
+                {
+                // Reset the free callstack
+                iFreeCallStack.Reset();
+                
+                // if XTI logging mode(s) we also log call stack in free.
+                if ( ( iLogOption == EATUseDefault || iLogOption == EATLogToXti || iLogOption == EATLogToXtiFast )
+                        && iFreeMaxCallStack > 0 )
+                    {
+                    for ( TInt i = 0; i < arrayCounter; i++ )
+                        {
+                        if ( i == KATMaxFreeCallstackLength || i == iFreeMaxCallStack )
+                            {
+                            break;
+                            }
+                        iFreeCallStack[i] = iReCallStack[i];
+                        }
+                    }
+                
+                // Try to remove old address from the storage server's
+                // leak array. If found it's removed from the array because system frees
+                // old address directly in the RHeap in ReAlloc case.
+                if ( iLogOption == EATLogToXtiFast )
+                    {
+                    ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack );
+                    }
+                else
+                    {
+                    iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack );
+                    }
+                }
+            
+            // Log the memory allocation information
+            if ( iLogOption == EATLogToXtiFast )
+                {
+                // Using fast xti.
+                ATFastLogMemoryAllocated( iProcessId, (TUint32) ptr, iFreeCallStack, aSize);
+                }
+            else
+                {
+                // Using storage server.
+                error = iStorageServer.LogMemoryAllocated( (TUint32) ptr, 
+                                                            iReCallStack, 
+                                                            aSize );
+                if ( KErrNone != error )
+                    {
+                    LOGSTR2( "ATMH LogMemoryAllocated ReAlloc error %i", error );
+                    switch ( error )
+                        {
+                        case KErrNoMemory:
+                        LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - KErrNoMemory case"  );
+                        if ( iStorageServerOpen )
+                            {
+                            iStorageServerOpen = EFalse;
+                            LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - close iStorageServer"  );
+                            iStorageServer.Close();
+                            }
+                        break;
+                        }
+                    }
+                }
+            }
+        }
+    
+    // Release the mutex
+    iMutex.Signal();
+
+    // Return pointer to the reallocated cell
+    return ptr; 
+    }
+
+#else
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::ReAlloc()
+// Increases or decreases the size of an existing cell.
+// -----------------------------------------------------------------------------
+//
+TAny* RAnalyzeToolAllocator::ReAlloc( TAny* aPtr, TInt aSize, TInt aMode )
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc()" );
+
+    // Acquire the mutex
+    iMutex.Wait();
+
+    // Realloc the memory using original allocator
+    TAny* ptr = iAllocator->ReAlloc( aPtr, aSize, aMode );
+
+    // NULL addresses are not in a process under test
+    if ( ptr && !( aMode & ENeverMove ) )
+        {
+        LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aPtr: %x, ptr: %x", 
+                (TUint32)aPtr, (TUint32)ptr );
+        LOGSTR3( "ATMH RAnalyzeToolAllocator::ReAlloc() - aSize: %i, aMode: %i", 
+                aSize, aMode );
+
+        // Don't collect or log data if storage server not open or logging mode fast xti.
+        if ( iStorageServerOpen || iLogOption == EATLogToXtiFast )
+            {
+            // Reset the callstack
+            iReCallStack.Reset(); 
+
+            // Find the current thread callstack start address
+            TUint32 stackstart( 0 ); 
+            TBool found( FindCurrentThreadStack( stackstart ) );
+            LOGSTR3( "ATMH > stackstart: %x , found = %i", stackstart, found );
+            
+            // Get codeblocks count
+            TInt blocksCount( iCodeblocks.Count() );
+            TInt error( KErrNone );
+            TUint arrayCounter = 0;
+            
+            for ( TUint32 i = __current_sp(); i < stackstart; i = i + KAddressLength )//lint !e1055 !e526 !e628 !e348
+                {
+                for ( TInt j = 0; j < blocksCount; j++ )
+                    {
+                    if ( iCodeblocks[j].CheckAddress( (TUint32) *( (TUint32*) i ) ) )
+                        {
+                        // To avoid recursive call to ReAlloc specifying granularity
+                        // Add address to the callstack
+                        iReCallStack[arrayCounter] = ( (TUint32) *( (TUint32*) i ) );
+                        arrayCounter++;
+                        break;
+                        }
+                    }
+                if ( arrayCounter == KATMaxCallstackLength || 
+                     arrayCounter == iAllocMaxCallStack )
+                    {
+                    LOGSTR2( "ATMH > Wanted CallStack items ready( %i )", arrayCounter );
+                    break;
+                    }
+                }
+            
+            // No need to report free if the aPtr was NULL
+            if ( aPtr != NULL )
+                {
+                // Reset the free callstack
+                iFreeCallStack.Reset();
+                
+                // if XTI logging mode(s) we also log call stack with free.
+                if ( ( iLogOption == EATUseDefault || iLogOption == EATLogToXti || iLogOption == EATLogToXtiFast )
+                        && iFreeMaxCallStack > 0 )
+                    {
+                    for ( TInt i = 0; i < arrayCounter; i++ )
+                        {
+                        if ( i == iFreeCallStack.Count() )
+                            {
+                            break;
+                            }
+                        iFreeCallStack[i] = iReCallStack[i];
+                        }
+                    }
+                
+                // Try to remove old address from the storage server's
+                // leak array. If found it's removed from the array because system frees
+                // old address directly in the RHeap in ReAlloc case.
+                if ( iLogOption == EATLogToXtiFast )
+                    {
+                    ATFastLogMemoryFreed( iProcessId, (TUint32) aPtr, iFreeCallStack );
+                    }
+                else
+                    {
+                    iStorageServer.LogMemoryFreed( (TUint32) aPtr, iFreeCallStack );
+                    }
+                }
+        
+            // Log the memory allocation information
+            if ( iLogOption == EATLogToXtiFast )
+                {
+                // Using fast xti.
+                ATFastLogMemoryAllocated( iProcessId, (TUint32) ptr, iReCallStack, aSize );
+                }
+            else
+                {
+                // Using storage server.
+                error = iStorageServer.LogMemoryAllocated( (TUint32) ptr, 
+                                                            iReCallStack, 
+                                                            aSize );
+                if ( KErrNone != error )
+                    {
+                    LOGSTR2( "ATMH LogMemoryAllocated ReAlloc error %i", error );
+                    switch ( error )
+                        {
+                        case KErrNoMemory:
+                        LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - KErrNoMemory case"  );
+                        if ( iStorageServerOpen )
+                            {
+                            iStorageServerOpen = EFalse;
+                            LOGSTR1( "ATMH RAnalyzeToolAllocator::ReAlloc() - close iStorageServer"  );
+                            iStorageServer.Close();
+                            }
+                        break;
+                        }
+                    }
+                }
+            }
+        }
+
+    // Release the mutex
+    iMutex.Signal();
+
+    // Return pointer to the reallocated cell
+    return ptr; 
+    }
+
+#endif // __WINS__
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Compress()
+// The function frees excess committed space from the top of the heap.
+// The size of the heap is never reduced below the minimum size 
+// specified during creation of the heap.
+// -----------------------------------------------------------------------------
+//
+TInt RAnalyzeToolAllocator::Compress()
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Compress()" );
+
+    // Acquire the mutex
+    iMutex.Wait();
+
+    // Compress the memory using original allocator
+    TInt compress = iAllocator->Compress();
+
+    // Release the mutex
+    iMutex.Signal();
+
+    // Return the space reclaimed
+    return compress;
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Reset()
+// Frees all allocated cells on this heap. 
+// -----------------------------------------------------------------------------
+//
+void RAnalyzeToolAllocator::Reset()
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Reset()" );
+
+    // Acquire the mutex
+    iMutex.Wait();
+
+    // Reset the memory using original allocator
+    iAllocator->Reset();
+
+    // Release the mutex
+    iMutex.Signal();
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::AllocSize()
+// Gets the number of cells allocated on this heap, and 
+// the total space allocated to them.
+// -----------------------------------------------------------------------------
+//
+TInt RAnalyzeToolAllocator::AllocSize( TInt& aTotalAllocSize ) const
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::AllocSize()" );
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Acquire the memory information using original allocator
+    TInt size = iAllocator->AllocSize( aTotalAllocSize );
+    
+    // Release the mutex
+    iMutex.Signal();
+    
+    // Return the number of cells allocated on this heap.
+    return size;
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Available()
+// Gets the total free space currently available on the heap and the 
+// space available in the largest free block. The space available 
+// represents the total space which can be allocated. Note that 
+// compressing the heap may reduce the total free space available 
+// and the space available in the largest free block.
+// -----------------------------------------------------------------------------
+//
+TInt RAnalyzeToolAllocator::Available( TInt& aBiggestBlock ) const
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Available()" );
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Acquire the memory information using original allocator
+    TInt available = iAllocator->Available( aBiggestBlock );
+    
+    // Release the mutex
+    iMutex.Signal();
+    
+    // Return the total free space currently available on the heap
+    return available;
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::AllocLen()
+// Gets the length of the available space in the specified 
+// allocated cell.
+// -----------------------------------------------------------------------------
+//
+TInt RAnalyzeToolAllocator::AllocLen( const TAny* aCell ) const
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::AllocLen()" ); 
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Acquire the memory information using original allocator
+    TInt len = iAllocator->AllocLen( aCell );
+    
+    // Release the mutex
+    iMutex.Signal();
+    
+    // Return the length of the available space in the allocated cell.
+    return len;
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::DebugFunction()
+// Invocates specified debug funtionality.
+// -----------------------------------------------------------------------------
+//
+TInt RAnalyzeToolAllocator::DebugFunction( TInt aFunc, TAny* a1, TAny* a2 )
+    {
+    LOGSTR2( "ATMH RAnalyzeToolAllocator::DebugFunction() %i", aFunc );
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Invocate debug funtion using original allocator
+    TInt debug = iAllocator->DebugFunction( aFunc, a1, a2 );
+    
+    switch( aFunc )
+		{  
+		case EMarkEnd:
+			{
+			// Disables the __UHEAP_MARKEND macro
+			LOGSTR1( "ATMH __UHEAP_MARKEND macro called" );
+			if ( debug > 0 )
+				{
+				LOGSTR2( "ATMH __UHEAP_MARKEND detects leaks: %d", debug );
+				// Because there is leaks the alloc panic will occur but
+				// lets return a zero to pretend that everything is OK
+				debug = 0;
+				}
+			}
+		break;
+		
+		default:
+			{
+			}
+		break;
+		}
+    
+    // Release the mutex
+    iMutex.Signal();
+    
+    // Return information of the debug function success
+    return debug;
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::Extension_()
+// Extension function
+// -----------------------------------------------------------------------------
+//
+TInt RAnalyzeToolAllocator::Extension_( TUint aExtensionId, TAny*& a0, 
+    TAny* a1 ) 
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::Extension_()" );
+    
+    // Acquire the mutex
+    iMutex.Wait();
+    
+    // Invocate extension funtion using original allocator
+    TInt ext = RAllocator::Extension_( aExtensionId, a0, a1 );
+    
+    // Release the mutex
+    iMutex.Signal();
+    
+    // Return information of the extension function success
+    return ext;
+    }
+
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::ShareHeap()
+// Share heap with other thread
+// -----------------------------------------------------------------------------
+//
+void RAnalyzeToolAllocator::ShareHeap()
+    {
+    LOGSTR1( "ATMH RAnalyzeToolAllocator::ShareHeap()" );
+    
+    // Call the overwrited Open function
+    Open();
+    }
+    
+// -----------------------------------------------------------------------------
+// RAnalyzeToolAllocator::FindCurrentThreadStack()
+// Find the current thread which is using the heap
+// -----------------------------------------------------------------------------
+//
+TBool RAnalyzeToolAllocator::FindCurrentThreadStack( TUint32& aStackStart )
+    {
+    LOGSTR2( "ATMH RAnalyzeToolAllocator::FindCurrentThreadStack(), count( %i )", 
+            iThreadArray.Count() );
+    
+    // Flag for indicating that right thread has been found
+    TBool found( EFalse );
+    // If threre is only one thread it must be the right thread
+    if ( iThreadArray.Count() == KThreadCount )
+        {
+        if ( !iThreadArray[ 0 ].ThreadStackStart( aStackStart ) )
+            {
+            // This MUST BE the right thread
+            //__ASSERT_ALWAYS( EFalse, AssertPanic( ECantFindRightThread ) );
+            }
+        else if ( iThreadArray[ 0 ].ThreadStackStart( aStackStart ) )
+            {
+            found = ETrue;
+            }
+        }
+    else
+        {
+        // Iterate through array to find right thread
+        TInt count( iThreadArray.Count() );
+        
+        for ( TInt i = 0; i < count; i++ )
+            {
+            // Check if this is the right thread
+            if ( iThreadArray[ i ].ThreadStackStart( aStackStart ) )
+                {
+                // Right thread found. Mark the flag
+                found = ETrue;
+                break;
+                }
+            }
+        // If right thread was not found the panic must be raised
+        if ( !found )
+            {
+            //__ASSERT_ALWAYS( EFalse, AssertPanic( ECantFindRightThread ) );
+            }
+        }
+    return found;
+    }
+
+// End of File