wlan_bearer/wlanldd/wlan_common/osa_common/src/osamemorypool.cpp
changeset 0 c40eb8fe8501
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanldd/wlan_common/osa_common/src/osamemorypool.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,600 @@
+/*
+* Copyright (c) 2007-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:   WlanMemoryPool implementation
+*
+*/
+
+/*
+* %version: 8 %
+*/
+
+#include "osa_includeme.h"
+
+#include <wlanosa.h>
+
+#include "osamemorypool.h"
+#include "osachunkbase.h"
+
+// allocator for general purpose memory
+extern void* GpAlloc( TInt aSize, TBool aZeroStamp );
+// free for general purpose memory
+extern void GpFree( void* aPtr );
+
+// don't derive form DBase as we use placement new
+struct SMemHeader
+    {
+#ifndef NDEBUG
+    enum  { KMagic = 0xBEEFCACE };
+    TInt  iMagicHead;
+#endif // !NDEBUG
+
+    TInt  iHwChunkId;
+
+    explicit SMemHeader( TInt aHwChunkId = 0 ) : 
+        #ifndef NDEBUG
+        iMagicHead( KMagic ),
+        #endif // NDEBUG
+        iHwChunkId( aHwChunkId )
+            {}; 
+
+private:
+
+    // Prohibit copy constructor.
+    SMemHeader( const SMemHeader& );
+    // Prohibit assigment operator.
+    SMemHeader& operator= ( const SMemHeader& );
+    };
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+WlanMemoryPool::WlanMemoryPool( TBool aUseCachedMemory, TInt aAllocationUnit )
+    : 
+    iUseCachedMemory( aUseCachedMemory ), 
+    iAllocationUnit( aAllocationUnit ),
+    iExtraPadding( 0 ) // actual value is determined later
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool ctor +: 0x%08x"), this));
+
+    const TBool ret( InitPool() );
+    if ( ret )
+        {
+        Validate();
+        }
+    else
+        {
+        TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
+        Trace( ERROR_LEVEL, 
+            reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+
+        InValidate();
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool ctor -: 0x%08x"), this));
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+WlanMemoryPool::~WlanMemoryPool()
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool dtor +: 0x%08x"), this));
+    }
+
+// ---------------------------------------------------------------------------
+//
+// ---------------------------------------------------------------------------
+//
+void* WlanMemoryPool::Alloc( 
+    MWlanOsa::TOsaMemoryType aOsaMemoryType, 
+    TInt aSize,
+    TBool aZeroStamp )
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::Alloc +: 0x%08x"), this));
+    TraceDump(MEMORYPOOL, (("[WLAN] memory type: %d"), aOsaMemoryType));
+    TraceDump(MEMORYPOOL, (("[WLAN] size: %d"), aSize));
+
+    TUint8* addr = NULL;
+
+    // length of our memory header
+    const TInt KOurHdrLen ( sizeof( SMemHeader ) );
+    // actual size is the requested size + our header
+    TInt alloc_size ( aSize + KOurHdrLen );     
+
+    if ( MWlanOsa::ENormalMemory == aOsaMemoryType )
+        {
+        // normal allocation requested
+        
+        addr = static_cast<TUint8*>(GpAlloc( alloc_size, aZeroStamp ));
+        if ( addr )
+            {
+            // set header 
+            new (addr) SMemHeader;
+            // set the address to be returned to the requester 
+            addr += KOurHdrLen;
+            }
+        else
+            {
+            // failed: left intentionally empty
+            }
+        }
+    else if ( MWlanOsa::EInterconnectMemory == aOsaMemoryType )
+        {
+        // hw pool allocation requested
+
+        // in this case we need to make sure that the memory buffer start
+        // address returned to the requester is aligned to allocation unit
+        // boundary. We do this by adding the necessary number of padding 
+        // bytes to the beginning of the allocated memory buffer
+        
+        alloc_size += iExtraPadding;     
+
+        TInt hw_chunk_id( 0 );
+        addr = static_cast<TUint8*>(HwChunkAlloc( 
+            alloc_size, hw_chunk_id, aZeroStamp ));
+        if ( addr )
+            {
+            // set header. The extra padding is before our header
+            new (addr + iExtraPadding) SMemHeader( hw_chunk_id );
+            // set the address to be returned to the requester 
+            addr += iExtraPadding + KOurHdrLen;
+            }
+        else
+            {
+            // failed: left intentionally empty
+            }
+        }
+    else
+        {
+        // unknown type
+        TraceDump(CRIT_LEVEL, (("[WLAN] critical: type: %d"), aOsaMemoryType));
+        MWlanOsa::Assert( reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+        }
+
+    if ( addr )
+        {
+        TraceDump(MEMORYPOOL, 
+            (("[WLAN] address to be returned to client: 0x%08x"), addr));
+        }
+    else
+        {
+        TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
+        Trace( ERROR_LEVEL, 
+            reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::Alloc -: 0x%08x"), this));
+
+    return addr;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanMemoryPool::Free( void* aPtr )
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::Free +: 0x%08x"), this));
+    TraceDump(MEMORYPOOL, (("[WLAN] free address: 0x%08x"), aPtr));
+
+    SMemHeader* hdr = ((static_cast<SMemHeader*>(aPtr)) - 1);
+
+    TraceDump(MEMORYPOOL, (("[WLAN] header free address: 0x%08x"), hdr));
+
+#ifndef NDEBUG
+    // validate magic 
+    MWlanOsa::Assert( reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
+        (SMemHeader::KMagic == hdr->iMagicHead) );
+#endif // !NDEBUG
+
+    if ( !(hdr->iHwChunkId) )
+        {        
+        GpFree( static_cast<void*>(hdr) );
+        }
+    else
+        {
+        HwChunkFree( *hdr );
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::Free -: 0x%08x"), this));
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanMemoryPool::InitPool()
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::InitPool +: 0x%08x"), this));
+
+    TBool ret( EFalse );
+
+    // create the initial hw chunk
+    WlanPlatformHwChunk* chunk = new WlanPlatformHwChunk( 
+        KInitialHwChunkSize, 
+        iUseCachedMemory,
+        iAllocationUnit );
+    if ( chunk )
+        {
+        if ( chunk->IsValid() )
+            {
+            // chunk is valid
+            HwChunkHandle handle( *chunk );
+            if ( handle->IsValid() )
+                {
+                // handle is valid
+                ret = PushBack( handle );
+                if ( ret )
+                    {
+                    // push success
+                    ret = ETrue;
+
+                    // determine the number of extra padding bytes needed on 
+                    // top of our memory header length for interconnect 
+                    // memory type so that the memory buffer start address 
+                    // returned to memory requester is always aligned to 
+                    // allocation unit boundary
+                    
+                    const TInt KNextLevelHdrLen = 
+                        (handle->Chunk()).HeaderSize();                    
+                    const TInt KRemainder ( 
+                        ( static_cast<TInt>(sizeof( SMemHeader )) 
+                          + KNextLevelHdrLen )
+                        % iAllocationUnit );                    
+                    iExtraPadding = KRemainder ? 
+                        ( iAllocationUnit - KRemainder ) : KRemainder;                    
+                    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+                        (("[WLAN] Extra padding: %d"), iExtraPadding));
+                    }
+                else
+                    {
+                    // push failure: left intentionally empty
+                    }
+                }
+            else
+                {
+                // handle is invalid: left intentionally empty
+                }
+            }
+        else
+            {
+            // chunk is invalid: left intentionally empty
+            }
+        }
+    else
+        {
+        // allocation failure: left intentionally empty
+        TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
+        Trace( ERROR_LEVEL, 
+            reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+        }
+
+    if ( !ret )
+        {
+        // something went wrong
+        delete chunk;
+        }
+    else
+        {
+        // left intentionally empty
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::InitPool -: 0x%08x"), this));
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+TBool WlanMemoryPool::PushBack( const HwChunkHandle& aHwChunkHandle )
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::PushBack +: 0x%08x"), this));
+
+    TBool ret( EFalse );
+    const size_type size( iHwChunkHandles.size() );
+
+    iHwChunkHandles.push_back( aHwChunkHandle );
+    if ( size != iHwChunkHandles.size() )
+        {
+        // size difference prior and after push
+        // so it must have been a success
+        ret = ETrue;
+        }
+    else
+        {
+        // push failure :left intentionally empty
+        TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
+        Trace( ERROR_LEVEL, 
+            reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::PushBack -: 0x%08x"), this));
+
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void* WlanMemoryPool::HwChunkAllocWithCreate( const TInt aSize, 
+                                              TInt& aHwChunkId,
+                                              TBool aZeroStamp )
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::HwChunkAlloc +: 0x%08x"), this));
+
+    // initial allocation try is times 1.4 the requested size
+    const TInt KInitialAllocSize( (aSize * 14) / 10 ); 
+    // try initial allocation amount + the requested amount times
+    const TInt KAllocationCounts( 2 );
+
+    const TInt allocation_size[KAllocationCounts] 
+        = { KInitialAllocSize, aSize };
+
+    const TInt* pos = allocation_size;  // start of sequence
+    // last of sequence
+    const TInt* const end = &( allocation_size[KAllocationCounts] );
+
+    WlanPlatformHwChunk* chunk = NULL;
+
+    // loop in order to acquire a chunk for us
+    do
+        {
+        chunk = new WlanPlatformHwChunk( 
+            *pos, 
+            iUseCachedMemory, 
+            iAllocationUnit );
+        if ( chunk )
+            {
+            if ( chunk->IsValid() )
+                {
+                // ok
+                break;
+                }
+            else
+                {
+                // invalid chunk: 
+                delete chunk;
+                chunk = NULL;
+                }
+            }
+        else
+            {
+            // allocation failure: left intentionally empty
+            TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
+            Trace( ERROR_LEVEL, 
+                reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
+            }
+
+        ++pos;
+        } while ( pos < end );
+
+    void* addr = NULL;
+
+    if ( chunk )
+        {
+        // chunk acquire success
+        // must also be valid at this point
+        MWlanOsa::Assert( 
+            reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
+            (chunk->IsValid()) );
+        
+        HwChunkHandle handle( *chunk );
+        if ( handle.IsValid() )
+            {
+            if ( PushBack( handle ) )
+                {
+                // allocation guaranteed as
+                // chunk final creation success
+                addr = chunk->Chunk().Alloc( 
+                    aSize, aZeroStamp );
+                MWlanOsa::Assert( 
+                    reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
+                    addr != NULL );
+
+                // set he hw chunk id for the caller
+                aHwChunkId = reinterpret_cast<TInt>(chunk);
+                }
+            else
+                {
+                // PushBack failure: left intentionally empty
+                }
+            }
+        else
+            {
+            // invalid handle: left intentionally empty
+            }
+
+        if ( !addr )
+            {
+            // if we don't have an address at this point 
+            // we don't need a chunk either
+            delete chunk;
+            }
+        else
+            {
+            // everything okay: left intentionally empty
+            }
+        }
+    else
+        {
+        // chunk acquire failure: left intentionally empty
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::HwChunkAlloc -: 0x%08x"), this));
+
+    return addr;
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void* WlanMemoryPool::HwChunkAlloc( const TInt aSize, 
+                                    TInt& aHwChunkId, 
+                                    TBool aZeroStamp )
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::HwChunkAlloc +: 0x%08x"), this));
+
+    // lets search a chunk for us
+    const_iterator end( iHwChunkHandles.end() );
+    iterator pos( iHwChunkHandles.begin() );
+
+    void* addr = NULL;
+
+    // always atleast one exists in the sequence
+    MWlanOsa::Assert( 
+        reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
+        (!(iHwChunkHandles.empty())) );
+
+    do 
+        {
+        addr = ((*pos)->Chunk()).Alloc( aSize, aZeroStamp );
+        if ( addr )
+            {
+            break;
+            }
+        else
+            {
+            // left intentionally empty
+            }
+            
+        ++pos;
+        } while ( pos != end );
+
+    if ( addr )
+        {
+        // allocation success: 
+        // set the hw chunk id
+        aHwChunkId = reinterpret_cast<TInt>((*pos).Data());
+        }
+    else
+        {
+        // failed to allocate
+        // we shall now create a new chunk for allocation
+        addr = HwChunkAllocWithCreate( aSize, aHwChunkId, aZeroStamp );
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::HwChunkAlloc -: 0x%08x"), this));
+
+    return addr;
+    }
+
+// ---------------------------------------------------------------------------
+// in the front of the sequence we always have our initial chunk,
+// the lifetime of which is to be equal to the lifetime of this object
+// ---------------------------------------------------------------------------
+//
+inline 
+TBool WlanMemoryPool::IsInitialChunk( WlanPlatformHwChunk* aChunk )
+    {
+    return ( aChunk == (iHwChunkHandles.front().Data()) );
+    }
+
+// ---------------------------------------------------------------------------
+// 
+// ---------------------------------------------------------------------------
+//
+void WlanMemoryPool::HwChunkFree( SMemHeader& aMemHeader )
+    {
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::HwChunkFree +: 0x%08x"), this));
+    
+    // extract correct hw_chunk
+    WlanPlatformHwChunk* hw_chunk 
+        = reinterpret_cast<WlanPlatformHwChunk*>(aMemHeader.iHwChunkId);
+
+    // deallocate; note the extra padding before our memory header 
+    hw_chunk->Chunk().Free( 
+        reinterpret_cast<TUint8*>(&aMemHeader) - iExtraPadding );
+
+    if ( IsInitialChunk( hw_chunk ) )
+        {
+        // is the initial chunk: left intentionally empty
+        }
+    else
+        {
+
+        // not the initial chunk
+        if ( !(hw_chunk->Chunk().IsInUse()) )
+            {
+            // the chunk is not inuse, this meaning nothing
+            // has been allocated from there, which means we can erase it
+
+            TraceDump(MEMORYPOOL, ("[WLAN] WlanMemoryPool erase unused chunk"));
+
+            // lets found the critter and erase it from the sequnce
+
+            iterator pos( iHwChunkHandles.begin() );
+            const_iterator end( iHwChunkHandles.end() );
+
+            // always atleast one exists in the sequence
+            MWlanOsa::Assert( 
+                reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
+                (!(iHwChunkHandles.empty())) );
+
+            do
+                {
+                if ( ((*pos).Data()) == hw_chunk )
+                    {
+                    // found a match
+                    break;
+                    }
+                else
+                    {
+                    // no match: left intentionally empty
+                    }
+
+                ++pos;
+                } while ( pos != end );
+
+            MWlanOsa::Assert( 
+                reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
+                (pos != end) );
+
+            // erase the critter
+            iHwChunkHandles.erase( pos );    
+            
+            }
+        else
+            {
+            // the chunk is in use
+            // left intentionally empty
+            }
+        }
+
+    TraceDump(INFO_LEVEL | MEMORYPOOL, 
+        (("[WLAN] WlanMemoryPool::HwChunkFree -: 0x%08x"), this));
+    }