wlan_bearer/wlanldd/wlan_common/osa_common/src/osamemorypool.cpp
changeset 0 c40eb8fe8501
equal deleted inserted replaced
-1:000000000000 0:c40eb8fe8501
       
     1 /*
       
     2 * Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   WlanMemoryPool implementation
       
    15 *
       
    16 */
       
    17 
       
    18 /*
       
    19 * %version: 8 %
       
    20 */
       
    21 
       
    22 #include "osa_includeme.h"
       
    23 
       
    24 #include <wlanosa.h>
       
    25 
       
    26 #include "osamemorypool.h"
       
    27 #include "osachunkbase.h"
       
    28 
       
    29 // allocator for general purpose memory
       
    30 extern void* GpAlloc( TInt aSize, TBool aZeroStamp );
       
    31 // free for general purpose memory
       
    32 extern void GpFree( void* aPtr );
       
    33 
       
    34 // don't derive form DBase as we use placement new
       
    35 struct SMemHeader
       
    36     {
       
    37 #ifndef NDEBUG
       
    38     enum  { KMagic = 0xBEEFCACE };
       
    39     TInt  iMagicHead;
       
    40 #endif // !NDEBUG
       
    41 
       
    42     TInt  iHwChunkId;
       
    43 
       
    44     explicit SMemHeader( TInt aHwChunkId = 0 ) : 
       
    45         #ifndef NDEBUG
       
    46         iMagicHead( KMagic ),
       
    47         #endif // NDEBUG
       
    48         iHwChunkId( aHwChunkId )
       
    49             {}; 
       
    50 
       
    51 private:
       
    52 
       
    53     // Prohibit copy constructor.
       
    54     SMemHeader( const SMemHeader& );
       
    55     // Prohibit assigment operator.
       
    56     SMemHeader& operator= ( const SMemHeader& );
       
    57     };
       
    58 
       
    59 // ======== MEMBER FUNCTIONS ========
       
    60 
       
    61 // ---------------------------------------------------------------------------
       
    62 // 
       
    63 // ---------------------------------------------------------------------------
       
    64 //
       
    65 WlanMemoryPool::WlanMemoryPool( TBool aUseCachedMemory, TInt aAllocationUnit )
       
    66     : 
       
    67     iUseCachedMemory( aUseCachedMemory ), 
       
    68     iAllocationUnit( aAllocationUnit ),
       
    69     iExtraPadding( 0 ) // actual value is determined later
       
    70     {
       
    71     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
    72         (("[WLAN] WlanMemoryPool ctor +: 0x%08x"), this));
       
    73 
       
    74     const TBool ret( InitPool() );
       
    75     if ( ret )
       
    76         {
       
    77         Validate();
       
    78         }
       
    79     else
       
    80         {
       
    81         TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
       
    82         Trace( ERROR_LEVEL, 
       
    83             reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
    84 
       
    85         InValidate();
       
    86         }
       
    87 
       
    88     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
    89         (("[WLAN] WlanMemoryPool ctor -: 0x%08x"), this));
       
    90     }
       
    91 
       
    92 // ---------------------------------------------------------------------------
       
    93 // 
       
    94 // ---------------------------------------------------------------------------
       
    95 //
       
    96 WlanMemoryPool::~WlanMemoryPool()
       
    97     {
       
    98     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
    99         (("[WLAN] WlanMemoryPool dtor +: 0x%08x"), this));
       
   100     }
       
   101 
       
   102 // ---------------------------------------------------------------------------
       
   103 //
       
   104 // ---------------------------------------------------------------------------
       
   105 //
       
   106 void* WlanMemoryPool::Alloc( 
       
   107     MWlanOsa::TOsaMemoryType aOsaMemoryType, 
       
   108     TInt aSize,
       
   109     TBool aZeroStamp )
       
   110     {
       
   111     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   112         (("[WLAN] WlanMemoryPool::Alloc +: 0x%08x"), this));
       
   113     TraceDump(MEMORYPOOL, (("[WLAN] memory type: %d"), aOsaMemoryType));
       
   114     TraceDump(MEMORYPOOL, (("[WLAN] size: %d"), aSize));
       
   115 
       
   116     TUint8* addr = NULL;
       
   117 
       
   118     // length of our memory header
       
   119     const TInt KOurHdrLen ( sizeof( SMemHeader ) );
       
   120     // actual size is the requested size + our header
       
   121     TInt alloc_size ( aSize + KOurHdrLen );     
       
   122 
       
   123     if ( MWlanOsa::ENormalMemory == aOsaMemoryType )
       
   124         {
       
   125         // normal allocation requested
       
   126         
       
   127         addr = static_cast<TUint8*>(GpAlloc( alloc_size, aZeroStamp ));
       
   128         if ( addr )
       
   129             {
       
   130             // set header 
       
   131             new (addr) SMemHeader;
       
   132             // set the address to be returned to the requester 
       
   133             addr += KOurHdrLen;
       
   134             }
       
   135         else
       
   136             {
       
   137             // failed: left intentionally empty
       
   138             }
       
   139         }
       
   140     else if ( MWlanOsa::EInterconnectMemory == aOsaMemoryType )
       
   141         {
       
   142         // hw pool allocation requested
       
   143 
       
   144         // in this case we need to make sure that the memory buffer start
       
   145         // address returned to the requester is aligned to allocation unit
       
   146         // boundary. We do this by adding the necessary number of padding 
       
   147         // bytes to the beginning of the allocated memory buffer
       
   148         
       
   149         alloc_size += iExtraPadding;     
       
   150 
       
   151         TInt hw_chunk_id( 0 );
       
   152         addr = static_cast<TUint8*>(HwChunkAlloc( 
       
   153             alloc_size, hw_chunk_id, aZeroStamp ));
       
   154         if ( addr )
       
   155             {
       
   156             // set header. The extra padding is before our header
       
   157             new (addr + iExtraPadding) SMemHeader( hw_chunk_id );
       
   158             // set the address to be returned to the requester 
       
   159             addr += iExtraPadding + KOurHdrLen;
       
   160             }
       
   161         else
       
   162             {
       
   163             // failed: left intentionally empty
       
   164             }
       
   165         }
       
   166     else
       
   167         {
       
   168         // unknown type
       
   169         TraceDump(CRIT_LEVEL, (("[WLAN] critical: type: %d"), aOsaMemoryType));
       
   170         MWlanOsa::Assert( reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
   171         }
       
   172 
       
   173     if ( addr )
       
   174         {
       
   175         TraceDump(MEMORYPOOL, 
       
   176             (("[WLAN] address to be returned to client: 0x%08x"), addr));
       
   177         }
       
   178     else
       
   179         {
       
   180         TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
       
   181         Trace( ERROR_LEVEL, 
       
   182             reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
   183         }
       
   184 
       
   185     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   186         (("[WLAN] WlanMemoryPool::Alloc -: 0x%08x"), this));
       
   187 
       
   188     return addr;
       
   189     }
       
   190 
       
   191 // ---------------------------------------------------------------------------
       
   192 // 
       
   193 // ---------------------------------------------------------------------------
       
   194 //
       
   195 void WlanMemoryPool::Free( void* aPtr )
       
   196     {
       
   197     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   198         (("[WLAN] WlanMemoryPool::Free +: 0x%08x"), this));
       
   199     TraceDump(MEMORYPOOL, (("[WLAN] free address: 0x%08x"), aPtr));
       
   200 
       
   201     SMemHeader* hdr = ((static_cast<SMemHeader*>(aPtr)) - 1);
       
   202 
       
   203     TraceDump(MEMORYPOOL, (("[WLAN] header free address: 0x%08x"), hdr));
       
   204 
       
   205 #ifndef NDEBUG
       
   206     // validate magic 
       
   207     MWlanOsa::Assert( reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
       
   208         (SMemHeader::KMagic == hdr->iMagicHead) );
       
   209 #endif // !NDEBUG
       
   210 
       
   211     if ( !(hdr->iHwChunkId) )
       
   212         {        
       
   213         GpFree( static_cast<void*>(hdr) );
       
   214         }
       
   215     else
       
   216         {
       
   217         HwChunkFree( *hdr );
       
   218         }
       
   219 
       
   220     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   221         (("[WLAN] WlanMemoryPool::Free -: 0x%08x"), this));
       
   222     }
       
   223 
       
   224 // ---------------------------------------------------------------------------
       
   225 // 
       
   226 // ---------------------------------------------------------------------------
       
   227 //
       
   228 TBool WlanMemoryPool::InitPool()
       
   229     {
       
   230     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   231         (("[WLAN] WlanMemoryPool::InitPool +: 0x%08x"), this));
       
   232 
       
   233     TBool ret( EFalse );
       
   234 
       
   235     // create the initial hw chunk
       
   236     WlanPlatformHwChunk* chunk = new WlanPlatformHwChunk( 
       
   237         KInitialHwChunkSize, 
       
   238         iUseCachedMemory,
       
   239         iAllocationUnit );
       
   240     if ( chunk )
       
   241         {
       
   242         if ( chunk->IsValid() )
       
   243             {
       
   244             // chunk is valid
       
   245             HwChunkHandle handle( *chunk );
       
   246             if ( handle->IsValid() )
       
   247                 {
       
   248                 // handle is valid
       
   249                 ret = PushBack( handle );
       
   250                 if ( ret )
       
   251                     {
       
   252                     // push success
       
   253                     ret = ETrue;
       
   254 
       
   255                     // determine the number of extra padding bytes needed on 
       
   256                     // top of our memory header length for interconnect 
       
   257                     // memory type so that the memory buffer start address 
       
   258                     // returned to memory requester is always aligned to 
       
   259                     // allocation unit boundary
       
   260                     
       
   261                     const TInt KNextLevelHdrLen = 
       
   262                         (handle->Chunk()).HeaderSize();                    
       
   263                     const TInt KRemainder ( 
       
   264                         ( static_cast<TInt>(sizeof( SMemHeader )) 
       
   265                           + KNextLevelHdrLen )
       
   266                         % iAllocationUnit );                    
       
   267                     iExtraPadding = KRemainder ? 
       
   268                         ( iAllocationUnit - KRemainder ) : KRemainder;                    
       
   269                     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   270                         (("[WLAN] Extra padding: %d"), iExtraPadding));
       
   271                     }
       
   272                 else
       
   273                     {
       
   274                     // push failure: left intentionally empty
       
   275                     }
       
   276                 }
       
   277             else
       
   278                 {
       
   279                 // handle is invalid: left intentionally empty
       
   280                 }
       
   281             }
       
   282         else
       
   283             {
       
   284             // chunk is invalid: left intentionally empty
       
   285             }
       
   286         }
       
   287     else
       
   288         {
       
   289         // allocation failure: left intentionally empty
       
   290         TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
       
   291         Trace( ERROR_LEVEL, 
       
   292             reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
   293         }
       
   294 
       
   295     if ( !ret )
       
   296         {
       
   297         // something went wrong
       
   298         delete chunk;
       
   299         }
       
   300     else
       
   301         {
       
   302         // left intentionally empty
       
   303         }
       
   304 
       
   305     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   306         (("[WLAN] WlanMemoryPool::InitPool -: 0x%08x"), this));
       
   307 
       
   308     return ret;
       
   309     }
       
   310 
       
   311 // ---------------------------------------------------------------------------
       
   312 // 
       
   313 // ---------------------------------------------------------------------------
       
   314 //
       
   315 TBool WlanMemoryPool::PushBack( const HwChunkHandle& aHwChunkHandle )
       
   316     {
       
   317     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   318         (("[WLAN] WlanMemoryPool::PushBack +: 0x%08x"), this));
       
   319 
       
   320     TBool ret( EFalse );
       
   321     const size_type size( iHwChunkHandles.size() );
       
   322 
       
   323     iHwChunkHandles.push_back( aHwChunkHandle );
       
   324     if ( size != iHwChunkHandles.size() )
       
   325         {
       
   326         // size difference prior and after push
       
   327         // so it must have been a success
       
   328         ret = ETrue;
       
   329         }
       
   330     else
       
   331         {
       
   332         // push failure :left intentionally empty
       
   333         TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
       
   334         Trace( ERROR_LEVEL, 
       
   335             reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
   336         }
       
   337 
       
   338     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   339         (("[WLAN] WlanMemoryPool::PushBack -: 0x%08x"), this));
       
   340 
       
   341     return ret;
       
   342     }
       
   343 
       
   344 // ---------------------------------------------------------------------------
       
   345 // 
       
   346 // ---------------------------------------------------------------------------
       
   347 //
       
   348 void* WlanMemoryPool::HwChunkAllocWithCreate( const TInt aSize, 
       
   349                                               TInt& aHwChunkId,
       
   350                                               TBool aZeroStamp )
       
   351     {
       
   352     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   353         (("[WLAN] WlanMemoryPool::HwChunkAlloc +: 0x%08x"), this));
       
   354 
       
   355     // initial allocation try is times 1.4 the requested size
       
   356     const TInt KInitialAllocSize( (aSize * 14) / 10 ); 
       
   357     // try initial allocation amount + the requested amount times
       
   358     const TInt KAllocationCounts( 2 );
       
   359 
       
   360     const TInt allocation_size[KAllocationCounts] 
       
   361         = { KInitialAllocSize, aSize };
       
   362 
       
   363     const TInt* pos = allocation_size;  // start of sequence
       
   364     // last of sequence
       
   365     const TInt* const end = &( allocation_size[KAllocationCounts] );
       
   366 
       
   367     WlanPlatformHwChunk* chunk = NULL;
       
   368 
       
   369     // loop in order to acquire a chunk for us
       
   370     do
       
   371         {
       
   372         chunk = new WlanPlatformHwChunk( 
       
   373             *pos, 
       
   374             iUseCachedMemory, 
       
   375             iAllocationUnit );
       
   376         if ( chunk )
       
   377             {
       
   378             if ( chunk->IsValid() )
       
   379                 {
       
   380                 // ok
       
   381                 break;
       
   382                 }
       
   383             else
       
   384                 {
       
   385                 // invalid chunk: 
       
   386                 delete chunk;
       
   387                 chunk = NULL;
       
   388                 }
       
   389             }
       
   390         else
       
   391             {
       
   392             // allocation failure: left intentionally empty
       
   393             TraceDump(ERROR_LEVEL, ("[WLAN] error: allocation"));
       
   394             Trace( ERROR_LEVEL, 
       
   395                 reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__ );
       
   396             }
       
   397 
       
   398         ++pos;
       
   399         } while ( pos < end );
       
   400 
       
   401     void* addr = NULL;
       
   402 
       
   403     if ( chunk )
       
   404         {
       
   405         // chunk acquire success
       
   406         // must also be valid at this point
       
   407         MWlanOsa::Assert( 
       
   408             reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
       
   409             (chunk->IsValid()) );
       
   410         
       
   411         HwChunkHandle handle( *chunk );
       
   412         if ( handle.IsValid() )
       
   413             {
       
   414             if ( PushBack( handle ) )
       
   415                 {
       
   416                 // allocation guaranteed as
       
   417                 // chunk final creation success
       
   418                 addr = chunk->Chunk().Alloc( 
       
   419                     aSize, aZeroStamp );
       
   420                 MWlanOsa::Assert( 
       
   421                     reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
       
   422                     addr != NULL );
       
   423 
       
   424                 // set he hw chunk id for the caller
       
   425                 aHwChunkId = reinterpret_cast<TInt>(chunk);
       
   426                 }
       
   427             else
       
   428                 {
       
   429                 // PushBack failure: left intentionally empty
       
   430                 }
       
   431             }
       
   432         else
       
   433             {
       
   434             // invalid handle: left intentionally empty
       
   435             }
       
   436 
       
   437         if ( !addr )
       
   438             {
       
   439             // if we don't have an address at this point 
       
   440             // we don't need a chunk either
       
   441             delete chunk;
       
   442             }
       
   443         else
       
   444             {
       
   445             // everything okay: left intentionally empty
       
   446             }
       
   447         }
       
   448     else
       
   449         {
       
   450         // chunk acquire failure: left intentionally empty
       
   451         }
       
   452 
       
   453     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   454         (("[WLAN] WlanMemoryPool::HwChunkAlloc -: 0x%08x"), this));
       
   455 
       
   456     return addr;
       
   457     }
       
   458 
       
   459 // ---------------------------------------------------------------------------
       
   460 // 
       
   461 // ---------------------------------------------------------------------------
       
   462 //
       
   463 void* WlanMemoryPool::HwChunkAlloc( const TInt aSize, 
       
   464                                     TInt& aHwChunkId, 
       
   465                                     TBool aZeroStamp )
       
   466     {
       
   467     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   468         (("[WLAN] WlanMemoryPool::HwChunkAlloc +: 0x%08x"), this));
       
   469 
       
   470     // lets search a chunk for us
       
   471     const_iterator end( iHwChunkHandles.end() );
       
   472     iterator pos( iHwChunkHandles.begin() );
       
   473 
       
   474     void* addr = NULL;
       
   475 
       
   476     // always atleast one exists in the sequence
       
   477     MWlanOsa::Assert( 
       
   478         reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
       
   479         (!(iHwChunkHandles.empty())) );
       
   480 
       
   481     do 
       
   482         {
       
   483         addr = ((*pos)->Chunk()).Alloc( aSize, aZeroStamp );
       
   484         if ( addr )
       
   485             {
       
   486             break;
       
   487             }
       
   488         else
       
   489             {
       
   490             // left intentionally empty
       
   491             }
       
   492             
       
   493         ++pos;
       
   494         } while ( pos != end );
       
   495 
       
   496     if ( addr )
       
   497         {
       
   498         // allocation success: 
       
   499         // set the hw chunk id
       
   500         aHwChunkId = reinterpret_cast<TInt>((*pos).Data());
       
   501         }
       
   502     else
       
   503         {
       
   504         // failed to allocate
       
   505         // we shall now create a new chunk for allocation
       
   506         addr = HwChunkAllocWithCreate( aSize, aHwChunkId, aZeroStamp );
       
   507         }
       
   508 
       
   509     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   510         (("[WLAN] WlanMemoryPool::HwChunkAlloc -: 0x%08x"), this));
       
   511 
       
   512     return addr;
       
   513     }
       
   514 
       
   515 // ---------------------------------------------------------------------------
       
   516 // in the front of the sequence we always have our initial chunk,
       
   517 // the lifetime of which is to be equal to the lifetime of this object
       
   518 // ---------------------------------------------------------------------------
       
   519 //
       
   520 inline 
       
   521 TBool WlanMemoryPool::IsInitialChunk( WlanPlatformHwChunk* aChunk )
       
   522     {
       
   523     return ( aChunk == (iHwChunkHandles.front().Data()) );
       
   524     }
       
   525 
       
   526 // ---------------------------------------------------------------------------
       
   527 // 
       
   528 // ---------------------------------------------------------------------------
       
   529 //
       
   530 void WlanMemoryPool::HwChunkFree( SMemHeader& aMemHeader )
       
   531     {
       
   532     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   533         (("[WLAN] WlanMemoryPool::HwChunkFree +: 0x%08x"), this));
       
   534     
       
   535     // extract correct hw_chunk
       
   536     WlanPlatformHwChunk* hw_chunk 
       
   537         = reinterpret_cast<WlanPlatformHwChunk*>(aMemHeader.iHwChunkId);
       
   538 
       
   539     // deallocate; note the extra padding before our memory header 
       
   540     hw_chunk->Chunk().Free( 
       
   541         reinterpret_cast<TUint8*>(&aMemHeader) - iExtraPadding );
       
   542 
       
   543     if ( IsInitialChunk( hw_chunk ) )
       
   544         {
       
   545         // is the initial chunk: left intentionally empty
       
   546         }
       
   547     else
       
   548         {
       
   549 
       
   550         // not the initial chunk
       
   551         if ( !(hw_chunk->Chunk().IsInUse()) )
       
   552             {
       
   553             // the chunk is not inuse, this meaning nothing
       
   554             // has been allocated from there, which means we can erase it
       
   555 
       
   556             TraceDump(MEMORYPOOL, ("[WLAN] WlanMemoryPool erase unused chunk"));
       
   557 
       
   558             // lets found the critter and erase it from the sequnce
       
   559 
       
   560             iterator pos( iHwChunkHandles.begin() );
       
   561             const_iterator end( iHwChunkHandles.end() );
       
   562 
       
   563             // always atleast one exists in the sequence
       
   564             MWlanOsa::Assert( 
       
   565                 reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
       
   566                 (!(iHwChunkHandles.empty())) );
       
   567 
       
   568             do
       
   569                 {
       
   570                 if ( ((*pos).Data()) == hw_chunk )
       
   571                     {
       
   572                     // found a match
       
   573                     break;
       
   574                     }
       
   575                 else
       
   576                     {
       
   577                     // no match: left intentionally empty
       
   578                     }
       
   579 
       
   580                 ++pos;
       
   581                 } while ( pos != end );
       
   582 
       
   583             MWlanOsa::Assert( 
       
   584                 reinterpret_cast<const TInt8*>(WLAN_FILE), __LINE__,
       
   585                 (pos != end) );
       
   586 
       
   587             // erase the critter
       
   588             iHwChunkHandles.erase( pos );    
       
   589             
       
   590             }
       
   591         else
       
   592             {
       
   593             // the chunk is in use
       
   594             // left intentionally empty
       
   595             }
       
   596         }
       
   597 
       
   598     TraceDump(INFO_LEVEL | MEMORYPOOL, 
       
   599         (("[WLAN] WlanMemoryPool::HwChunkFree -: 0x%08x"), this));
       
   600     }