connectivitylayer/isce/memmanager_dll/src/memmanager.cpp
changeset 0 63b37f68c1ce
child 5 8ccc39f9d787
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectivitylayer/isce/memmanager_dll/src/memmanager.cpp	Fri Nov 06 17:28:23 2009 +0000
@@ -0,0 +1,406 @@
+/*
+* 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 the License "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: 
+*
+*/
+
+
+
+#include <platform.h> // For DPlatChunkHw           
+#include <nk_priv.h>  // For __ASSERT_NO_FAST_MUTEX (published to partners)
+
+#include "memmanager.h"             // For MemManager
+#include "memmanagertrace.h"        // For C_TRACE...
+
+DMemManager* DMemManager::iThisptr = NULL;
+TDfcQue* DMemManager::iDfcQueue = NULL;
+
+
+// Memory management fault enumerations
+enum TMemFault
+   {
+   EMemBlockAllocationFailed    = 0,
+   EMemBlockSizeZero,
+   EExtensionMemoryAllocationFailed,
+   EDfcCreateFailed,
+   EDfcQueueCreateFailed,
+   EInvalidParameter,
+   EPhysicalMemReleaseFailed,
+   EMemoryAllocationFailed,
+   EHWMemAllocFailed,
+   EPhysicalMemAllocFailed,
+   EInvalidQueueCount,
+   EAllocNotThreadContext,
+   EDeallocNotThreadContext,
+   EMemBlockInvalidReleaseDetected
+   };
+
+/*
+* Constructor.
+*/
+DMemManager::DMemManager()
+    {
+
+    C_TRACE( ( _T( "DMemManager::DMemManager>" ) ) );
+    
+    iFastMutex = new NFastMutex();
+    ASSERT_RESET_ALWAYS( iFastMutex, ( EMemoryAllocationFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    
+    //Priority must be larger than the threads calling alloc and dealloc
+    Kern::DfcQCreate( iDfcQueue, 28, &KMemManagerDfcQThreadName );
+    ASSERT_RESET_ALWAYS( ( iDfcQueue ), ( EDfcQueueCreateFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+      
+    iPoolAllocateDfc = new TDfc( PoolAllocateDfc, this, iDfcQueue, KPoolAllocateDfcPriority );
+    ASSERT_RESET_ALWAYS( ( iPoolAllocateDfc ), ( EDfcCreateFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+      
+    iPoolDeleteDfc = new TDfc( PoolDeleteDfc, this, iDfcQueue , KPoolDeleteDfcPriority );
+    ASSERT_RESET_ALWAYS( ( iPoolDeleteDfc ), ( EDfcCreateFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+   
+    //Static array configuration
+    iMemPond.Append( new DMemPool( 16, 384 ) );
+    iMemPond.Append( new DMemPool( 32, 128 ) );
+    iMemPond.Append( new DMemPool( 64, 64 ) );
+    iMemPond.Append( new DMemPool( 128, 80 ) );
+    iMemPond.Append( new DMemPool( 256, 60 ) );
+    iMemPond.Append( new DMemPool( 2048, 100 ) );
+    iMemPond.Append( new DMemPool( 4096, 100 ) );
+    iMemPond.Append( new DMemPool( 65524, 4 ) );
+    
+    C_TRACE( ( _T( "DMemManager::DMemManager<" ) ) );
+    }
+
+/*
+* Destructor.
+*/
+DMemManager::~DMemManager()
+    {
+    C_TRACE( ( _T( "DMemManager::~DMemManager>" ) ) );
+      
+    for( int i = 0; i < iMemPond.Count(); i++ )
+        {
+        delete iMemPond[i];
+    	  }
+    
+    iMemPond.Reset();
+        
+    for( int i = 0; i < iPoolCreateQueue.Count(); i++ )
+        {
+        delete iPoolCreateQueue[i];
+    	  }
+    
+    iPoolCreateQueue.Reset();
+        	  
+    for( TInt i = 0; i < iPoolDeleteQueue.Count(); i++ )
+        {
+        delete iPoolDeleteQueue[i];
+    	  }
+    
+    iPoolDeleteQueue.Reset();
+        
+    delete iFastMutex;
+    iFastMutex = NULL;
+   
+    C_TRACE( ( _T( "DMemManager::~DMemManager<" ) ) );
+    }
+
+/*
+* DFC for dynamic pool allocation.
+*/
+void DMemManager::PoolAllocateDfc(
+        TAny* aPtr  // Pointer to this object.
+        )
+    {
+    C_TRACE( ( _T( "DMemManager::PoolAllocateDfc aPtr 0x%x>" ), aPtr ) );
+            
+    DMemManager& tmp = *reinterpret_cast<DMemManager*>( aPtr );
+    
+    NKern::FMWait( tmp.iFastMutex );
+    
+    ASSERT_RESET_ALWAYS( ( tmp.iPoolCreateQueue.Count() > 0 ), ( EInvalidQueueCount | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    TInt index = tmp.iMemPond.Find( tmp.iPoolCreateQueue[0] );
+    ( tmp.iMemPond[ index ] )->iCopyPoolInUse = ETrue;
+    tmp.iMemPond.Insert( (new DMemPool( tmp.iPoolCreateQueue[0]->iBlockSize, tmp.iPoolCreateQueue[0]->iBlockNum ) ), index );
+    tmp.iPoolCreateQueue.Remove(0);
+    
+    NKern::FMSignal( tmp.iFastMutex );
+    
+    C_TRACE( ( _T( "DMemManager::PoolAllocateDfc<" ) ) );
+    }
+
+/*
+* DFC for dynamic pool deletion.
+*/
+void DMemManager::PoolDeleteDfc(
+        TAny* aPtr  // Pointer to this object.
+        )
+    {
+    C_TRACE( ( _T( "DMemManager::PoolDeleteDfc aPtr 0x%x>" ), aPtr ) );
+            
+    DMemManager& tmp = *reinterpret_cast<DMemManager*>( aPtr );
+    
+    NKern::FMWait( tmp.iFastMutex );
+    
+    ASSERT_RESET_ALWAYS( ( tmp.iPoolDeleteQueue.Count() > 0 ), ( EInvalidQueueCount | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    delete tmp.iPoolDeleteQueue[0];
+    tmp.iPoolDeleteQueue.Remove(0);
+ 
+    NKern::FMSignal( tmp.iFastMutex );
+    
+    C_TRACE( ( _T( "DMemManager::PoolDeleteDfc<" ) ) );
+    }
+
+
+/*
+* Constructor.
+*/
+DMemManager::DMemPool::DMemPool( const TUint16 aUnitSize, const TUint16 aUnitNum ) :
+    iAllocatedMemBlock(NULL), iFreeMemBlock(NULL), iMemoryArea(NULL), 
+    iPoolSize( aUnitNum * ( aUnitSize + sizeof(struct sUnit) ) ), 
+    iBlockSize( aUnitSize ), iBlockNum( aUnitNum ),
+    iBlockUsage(0), iHwChunk(NULL), iPhysicalAddress(0)
+    {
+    C_TRACE( ( _T( "DMemManager::DMemPool::DMemPool aUnitSize 0x%x, aUnitNum 0x%x>" ), aUnitSize, aUnitNum ) );
+	  
+	  ASSERT_RESET_ALWAYS( ((aUnitSize || aUnitNum) != 0 ), ( EInvalidParameter | EDMemmanagerTraceId << KClassIdentifierShift ) );
+
+#ifndef __WINS__	  
+    TInt r = Epoc::AllocPhysicalRam( iPoolSize, iPhysicalAddress );
+    ASSERT_RESET_ALWAYS( (  r == KErrNone ), ( EPhysicalMemAllocFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+  
+    // Create chunk as: non accessible from user side and non-cached.
+
+    r = DPlatChunkHw::New( iHwChunk, iPhysicalAddress, iPoolSize, EMapAttrSupRw | EMapAttrFullyBlocking );
+    ASSERT_RESET_ALWAYS( ( r == KErrNone ), ( EHWMemAllocFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+   
+    iMemoryArea = (TUint8*)(iHwChunk->LinearAddress());
+    ASSERT_RESET_ALWAYS( ( iMemoryArea ), ( EPhysicalMemAllocFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    
+#else
+    iMemoryArea = (TUint8*)Kern::Alloc( iPoolSize );
+    //ASSERT_RESET_ALWAYS( (  r == KErrNone ), ( EPhysicalMemAllocFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+  
+    // Create chunk as: non accessible from user side and non-cached.
+   
+    //iMemoryArea = (TUint8*)(iPoolSize/*->LinearAddress()*/);
+    ASSERT_RESET_ALWAYS( ( iMemoryArea ), ( EPhysicalMemAllocFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+#endif // __WINS__
+    
+    for( TUint16 i = 0; i < aUnitNum; i++ )  //Link all mem unit . Create linked list.
+        {
+        struct sUnit *pCurUnit = (struct sUnit *)( iMemoryArea + i*(aUnitSize+sizeof(struct sUnit)) );
+                                    
+        pCurUnit->iPrev = NULL;
+        pCurUnit->iNext = iFreeMemBlock;    //Insert the new unit at head.
+            
+        if(NULL != iFreeMemBlock)
+            {
+            iFreeMemBlock->iPrev = pCurUnit;
+            }
+                      
+        pCurUnit->iMemPtr = new TPtr8( ((TUint8*)pCurUnit + sizeof(struct sUnit)) , 0, iBlockSize );
+                     
+        iFreeMemBlock = pCurUnit;        
+        }
+      
+    iHighWaterMark = ( KPoolHighWaterLimit * aUnitNum ) / 100;
+
+    C_TRACE( ( _T( "DMemManager::DMemPool::DMemPool<" ) ) );
+    }
+
+/*
+* Destructor.
+*/
+DMemManager::DMemPool::~DMemPool()
+    {
+    C_TRACE( ( _T( "DMemManager::DMemPool::~DMemPool>" ) ) );
+    
+    for( TUint16 i = 0; i < iBlockNum; i++ )
+        {
+        struct sUnit *pCurUnit = (struct sUnit *)( iMemoryArea + i*(iBlockSize+sizeof(struct sUnit)) );
+                   
+        if( pCurUnit->iMemPtr )   
+            {
+            delete pCurUnit->iMemPtr;
+            pCurUnit->iMemPtr = NULL;
+            }
+        }
+#ifndef __WINS__        
+    TInt r = Epoc::FreePhysicalRam( iPhysicalAddress, iPoolSize );
+    ASSERT_RESET_ALWAYS( ( r == KErrNone ), ( EPhysicalMemReleaseFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    
+    iHwChunk->Close(NULL);
+    
+    iHwChunk = NULL;
+#else
+
+    Kern::Free( iMemoryArea );
+
+#endif // __WINS__    
+       
+    C_TRACE( ( _T( "DMemManager::DMemPool::~DMemPool<" ) ) );
+    }
+
+
+/*
+* Allocate memory unit.
+*/
+TPtr8* DMemManager::DMemPool::Alloc( const TUint16 aSize )
+    {
+	  C_TRACE( ( _T( "DMemManager::DMemPool::Alloc>" ) ) );
+	  
+	  ASSERT_RESET_ALWAYS( (iMemoryArea || iFreeMemBlock), ( EMemBlockAllocationFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    
+    struct sUnit *pCurUnit = iFreeMemBlock;
+
+    iFreeMemBlock = pCurUnit->iNext;
+
+    if( iFreeMemBlock )
+        {
+        iFreeMemBlock->iPrev = NULL;
+        }
+
+    pCurUnit->iNext = iAllocatedMemBlock;
+
+    if( iAllocatedMemBlock )
+        {
+        iAllocatedMemBlock->iPrev = pCurUnit; 
+        }
+
+    iAllocatedMemBlock = pCurUnit;
+    
+    iBlockUsage++;
+   
+	  C_TRACE( ( _T( "DMemManager::DMemPool::Alloc<" ) ) );
+    return iAllocatedMemBlock->iMemPtr;
+    }
+
+
+/*
+* Free memory unit.
+*/
+TBool DMemManager::DMemPool::Free( const TUint8* aBlockAddress )
+    {
+    C_TRACE( ( _T( "DMemManager::DMemPool::Free>" ) ) );
+	    
+    struct sUnit *pCurUnit = (struct sUnit *)(aBlockAddress - sizeof(struct sUnit) );
+
+    iAllocatedMemBlock = pCurUnit->iNext;
+        
+    if(NULL != iAllocatedMemBlock)
+        {
+        iAllocatedMemBlock->iPrev = NULL;
+        }
+        
+    pCurUnit->iNext = iFreeMemBlock;
+
+    if(NULL != iFreeMemBlock)
+        {
+        iFreeMemBlock->iPrev = pCurUnit;
+        }
+
+    iFreeMemBlock = pCurUnit;
+    iFreeMemBlock->iMemPtr->Zero();
+    iBlockUsage--;
+    
+    C_TRACE( ( _T( "DMemManager::DMemPool::Free<" ) ) );
+
+    //If empty & ready to be deleted
+    return ( iCopyPoolInUse && iBlockUsage == 0 ) ? ETrue : EFalse; 
+ 
+    }
+
+EXPORT_C TDes8& MemApi::AllocBlock( const TUint16 aSize )
+    {
+    C_TRACE( ( _T( "MemApi::AllocBlock 0x%x>" ), aSize ) );
+  
+    __ASSERT_NO_FAST_MUTEX;
+    
+    ASSERT_RESET_ALWAYS( ( aSize > 0 ), ( EMemBlockSizeZero | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    ASSERT_THREAD_CONTEXT_ALWAYS( ( EAllocNotThreadContext | EDMemmanagerTraceId << KClassIdentifierShift ) );
+  
+    TPtr8* ptr( NULL );
+  
+    NKern::FMWait( DMemManager::iThisptr->iFastMutex );
+ 
+    for( TUint8 i( 0 ); i < DMemManager::iThisptr->iMemPond.Count(); ++i )
+        {
+        if( aSize <= DMemManager::iThisptr->iMemPond[ i ]->iBlockSize )
+            {
+            ptr = DMemManager::iThisptr->iMemPond[i]->Alloc( aSize );
+           
+            if( DMemManager::iThisptr->iMemPond[i]->iBlockUsage > DMemManager::iThisptr->iMemPond[i]->iHighWaterMark )
+                {          	                        
+                DMemManager::iThisptr->iPoolCreateQueue.Append( DMemManager::iThisptr->iMemPond[i] );
+                DMemManager::iThisptr->iPoolAllocateDfc->Enque();   
+                }
+
+            NKern::FMSignal( DMemManager::iThisptr->iFastMutex );
+            break;
+            }
+        }
+  
+    ASSERT_RESET_ALWAYS( ptr, ( EMemBlockAllocationFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    ASSERT_RESET_ALWAYS( ptr->Size() == 0, ( EMemBlockInvalidReleaseDetected | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    
+    C_TRACE( ( _T( "MemApi::AllocBlock 0x%x<" ), ptr ) );
+    return *ptr;
+    }
+
+
+EXPORT_C void MemApi::DeallocBlock( TDes8& aBlock )
+    {
+    C_TRACE( ( _T( "MemApi::DeallocBlock aBlock 0x%x>" ), &aBlock ) );
+    
+    __ASSERT_NO_FAST_MUTEX;
+    
+    ASSERT_THREAD_CONTEXT_ALWAYS( ( EDeallocNotThreadContext | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    
+    TBool removePool = EFalse;
+    NKern::FMWait( DMemManager::iThisptr->iFastMutex );
+    
+    for( TUint8 i( 0 ); i < DMemManager::iThisptr->iMemPond.Count(); ++i )
+        {
+        //Check if inside pools memory area
+        if( ( (DMemManager::iThisptr->iMemPond[i]->iMemoryArea) < aBlock.Ptr() ) &&
+            ( aBlock.Ptr() < (DMemManager::iThisptr->iMemPond[i]->iMemoryArea + DMemManager::iThisptr->iMemPond[i]->iPoolSize) ) )
+            {
+            removePool = DMemManager::iThisptr->iMemPond[i]->Free( aBlock.Ptr() );   
+              
+            if( removePool )
+                {
+                DMemManager::iThisptr->iPoolDeleteQueue.Append( DMemManager::iThisptr->iMemPond[i] );
+                DMemManager::iThisptr->iMemPond.Remove( i );
+                DMemManager::iThisptr->iPoolDeleteDfc->Enque();
+                }
+              
+            break;
+            }
+        }
+   
+    NKern::FMSignal( DMemManager::iThisptr->iFastMutex );
+   
+    }
+
+DECLARE_STANDARD_EXTENSION()
+    {
+    Kern::Printf( "Memory Manager Extension>" );
+    DMemManager* extension = new DMemManager();
+    ASSERT_RESET_ALWAYS( ( extension ), ( EExtensionMemoryAllocationFailed | EDMemmanagerTraceId << KClassIdentifierShift ) );
+    DMemManager::iThisptr = static_cast< DMemManager* >( extension );
+    Kern::Printf( "Memory Manager Extension<" );
+    return KErrNone;
+    }
+
+//  End of File
+