wlan_bearer/wlanldd/wlan_common/osa_common/src/osaheap.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:   WlanHeap implementation
       
    15 *
       
    16 */
       
    17 
       
    18 /*
       
    19 * %version: 3 %
       
    20 */
       
    21 
       
    22 #include <kernel.h>
       
    23 #include <e32cmn.h>
       
    24 #include "osaheap.h"
       
    25 
       
    26 #define __NEXT_CELL(p)              ((SCell*)(((TUint8*)p)+p->len))
       
    27 
       
    28 #define __ALIGN_X( _x,_y) (((_x) + ((_y) - 1)) & (~((_y) - 1)))
       
    29 
       
    30 // ---------------------------------------------------------------------------
       
    31 // 
       
    32 // ---------------------------------------------------------------------------
       
    33 //
       
    34 RWlanHeap* RWlanHeap::FixedHeap(
       
    35         TAny* aBase, 
       
    36         TInt aInitialSize,
       
    37         TInt aAllocationUnit )
       
    38     {
       
    39     return new(aBase) RWlanHeap(aInitialSize, aAllocationUnit );
       
    40     }
       
    41 
       
    42 // ---------------------------------------------------------------------------
       
    43 // 
       
    44 // ---------------------------------------------------------------------------
       
    45 //
       
    46 RWlanHeap::RWlanHeap(TInt aMaxLength, TInt aAlign )
       
    47     :   iMinLength(aMaxLength), iMaxLength(aMaxLength), iOffset(0), iGrowBy(0), iChunkHandle(0)
       
    48     {
       
    49     iAlign = aAlign ? aAlign : ECellAlignment;
       
    50     iPageSize = 0;
       
    51     Initialise();
       
    52     }
       
    53 
       
    54 // ---------------------------------------------------------------------------
       
    55 // 
       
    56 // ---------------------------------------------------------------------------
       
    57 //
       
    58 TAny* RWlanHeap::operator new(TUint aSize, TAny* aBase)
       
    59     {
       
    60     RWlanHeap* h = (RWlanHeap*)aBase;
       
    61     h->iAlign = 0x80000000; // garbage value
       
    62     h->iBase = ((TUint8*)aBase) + aSize;
       
    63     return aBase;
       
    64     }
       
    65 
       
    66 // ---------------------------------------------------------------------------
       
    67 // 
       
    68 // ---------------------------------------------------------------------------
       
    69 //
       
    70 void RWlanHeap::Initialise()
       
    71     {
       
    72     
       
    73     // Base address must be aligned to AllocationUnit
       
    74     iBase = (TUint8*)__ALIGN_X((TUint32)iBase + EAllocCellSize, iAlign );
       
    75     TInt b = iBase - ((TUint8*)this - iOffset);
       
    76     TInt len = _ALIGN_DOWN(iMinLength - b, iAlign);
       
    77     iTop = iBase + len;
       
    78     iMinLength = iTop - ((TUint8*)this - iOffset);
       
    79     
       
    80     // Min cell size equals to allocationUnit
       
    81     iMinCell = iAlign;
       
    82     
       
    83     SCell* pM = (SCell*)iBase; // First free cell
       
    84     iFree.next = pM; // Free list points to first free cell
       
    85     iFree.len = 0; // Stop free from joining this with a free block
       
    86     pM->next = NULL; // Terminate the free list
       
    87     pM->len = len; // Set the size of the free cell
       
    88     }
       
    89 
       
    90 // ---------------------------------------------------------------------------
       
    91 // 
       
    92 // ---------------------------------------------------------------------------
       
    93 //
       
    94 TAny* RWlanHeap::Alloc(TInt aSize)
       
    95     {
       
    96     // The size of allocatoted block MUST be aligned to allocationUnit
       
    97     aSize = Max(__ALIGN_X(aSize + EAllocCellSize, iAlign), iMinCell );
       
    98     
       
    99     SCell* pL = NULL;
       
   100     SCell* pC = (SCell*)DoAlloc(aSize, pL);
       
   101 
       
   102     if (pC)
       
   103         {
       
   104         TAny* result = ((TUint8*)pC) + EAllocCellSize;
       
   105         return result;
       
   106         }
       
   107     return NULL;
       
   108     }
       
   109 
       
   110 // ---------------------------------------------------------------------------
       
   111 // 
       
   112 // ---------------------------------------------------------------------------
       
   113 //
       
   114 UEXPORT_C void RWlanHeap::Free(TAny* aCell)
       
   115     {
       
   116     if (!aCell)
       
   117         {
       
   118         return;
       
   119         }
       
   120     SCell* pC = GetAddress(aCell);
       
   121     DoFree(pC);
       
   122 
       
   123     }
       
   124 
       
   125 // ---------------------------------------------------------------------------
       
   126 // 
       
   127 // ---------------------------------------------------------------------------
       
   128 //
       
   129 UEXPORT_C RWlanHeap::SCell* RWlanHeap::GetAddress(const TAny* aCell) const
       
   130     {
       
   131     SCell* pC = (SCell*)(((TUint8*)aCell)-EAllocCellSize);
       
   132     return pC;
       
   133     }
       
   134 
       
   135 // ---------------------------------------------------------------------------
       
   136 // 
       
   137 // ---------------------------------------------------------------------------
       
   138 //
       
   139 UEXPORT_C TInt RWlanHeap::AllocLen(const TAny* aCell) const
       
   140     {
       
   141 
       
   142     SCell* pC = GetAddress(aCell);
       
   143     return pC->len - EAllocCellSize;
       
   144     }
       
   145 
       
   146 // ---------------------------------------------------------------------------
       
   147 // 
       
   148 // ---------------------------------------------------------------------------
       
   149 //
       
   150 RWlanHeap::SCell* RWlanHeap::DoAlloc(TInt aSize, SCell*& aLastFree)
       
   151     {
       
   152     SCell* pP = &iFree;
       
   153     SCell* pC = pP->next;
       
   154     for (; pC; pP=pC, pC=pC->next) // Scan the free list
       
   155         {
       
   156         SCell* pE;
       
   157         if (pC->len >= aSize)               // Block size bigger than request
       
   158             {
       
   159             if (pC->len - aSize < iMinCell) // Leftover must be large enough to hold an SCell
       
   160                 {
       
   161                 aSize = pC->len;            // It isn't, so take it all
       
   162                 pE = pC->next;              // Set the next field
       
   163                 }
       
   164             else
       
   165                 {
       
   166                 pE = (SCell*)(((TUint8*)pC)+aSize); // Take amount required
       
   167                 pE->len = pC->len - aSize;  // Initialize new free cell
       
   168                 pE->next = pC->next;
       
   169                 }
       
   170             pP->next = pE;                  // Update previous pointer
       
   171             pC->len = aSize;                // Set control size word
       
   172             return pC;
       
   173             }
       
   174         }
       
   175     aLastFree = pP;
       
   176     return NULL;
       
   177     }
       
   178 
       
   179 // ---------------------------------------------------------------------------
       
   180 // 
       
   181 // ---------------------------------------------------------------------------
       
   182 //
       
   183 void RWlanHeap::DoFree(SCell* pC)
       
   184     {
       
   185     SCell* pP = &iFree;
       
   186     SCell* pE = pP->next;
       
   187     for (; pE && pE<pC; pP=pE, pE=pE->next) {}
       
   188     if (pE)         // Is there a following free cell?
       
   189         {
       
   190         SCell* pN = __NEXT_CELL(pC);
       
   191         if (pN==pE) // Is it adjacent
       
   192             {
       
   193             pC->len += pE->len; // Yes - coalesce adjacent free cells
       
   194             pC->next = pE->next;
       
   195             }
       
   196         else                    // pN<pE, non-adjacent free cells
       
   197             {
       
   198             pC->next = pE;      // Otherwise just point to it
       
   199             }
       
   200         }
       
   201     else
       
   202         {
       
   203         pC->next = NULL;        // No following free cell
       
   204         }
       
   205     SCell* pN = __NEXT_CELL(pP);    // pN=pP=&iFree if no preceding free cell
       
   206     if (pN==pC) // Is it adjacent
       
   207         {
       
   208         pP->len += pC->len;     // Yes - coalesce adjacent free cells
       
   209         pP->next = pC->next;
       
   210         pC = pP;                // for size reduction check
       
   211         }
       
   212     else                        // pN<pC, non-adjacent free cells
       
   213         {
       
   214         pP->next = pC;          // point previous cell to the one being freed
       
   215         }
       
   216     pN = __NEXT_CELL(pC);       // End of amalgamated free cell
       
   217     }
       
   218 
       
   219 // ---------------------------------------------------------------------------
       
   220 // 
       
   221 // ---------------------------------------------------------------------------
       
   222 //
       
   223 void RWlanHeap::FindFollowingFreeCell(SCell* aCell, SCell*& aPrev, SCell*& aNext)
       
   224     {
       
   225     aPrev = &iFree;
       
   226     aNext = aPrev->next;
       
   227     for (; aNext && aNext < aCell; aPrev = aNext, aNext = aNext->next ) {} 
       
   228     
       
   229     if (aNext) // If there is a following free cell, check its directly after aCell.
       
   230         {
       
   231             SCell* pNextCell = __NEXT_CELL(aCell);          // end of this cell
       
   232             if (pNextCell!= aNext) 
       
   233                 {
       
   234                 aNext = NULL;     
       
   235                 }
       
   236         }
       
   237     }
       
   238 
       
   239 // ---------------------------------------------------------------------------
       
   240 // 
       
   241 // ---------------------------------------------------------------------------
       
   242 //
       
   243 TInt RWlanHeap::TryToGrowCell(SCell* aCell,SCell* aPrev, SCell* aNext, TInt aSize)
       
   244     {
       
   245     TInt extra = aSize - aCell->len;
       
   246     if (aNext && (aNext->len >= extra)) // Is there a following free cell big enough?
       
   247         {
       
   248         if (aNext->len - extra >= iMinCell) // take part of free cell ?
       
   249             {
       
   250             SCell* pX = (SCell*)((TUint8*)aNext + extra);   // remainder of free cell
       
   251             pX->next = aNext->next;         // remainder->next = original free cell->next
       
   252             pX->len = aNext->len - extra;       // remainder length = original free cell length - extra
       
   253             aPrev->next = pX;                   // put remainder into free chain
       
   254             }
       
   255         else
       
   256             {
       
   257             extra = aNext->len;                 // Take whole free cell
       
   258             aPrev->next = aNext->next;          // remove from free chain
       
   259             }
       
   260      
       
   261         aCell->len += extra;                    // update reallocated cell length
       
   262         
       
   263         return KErrNone;
       
   264         }
       
   265     return KErrGeneral;  // No space to grow cell
       
   266     }
       
   267 
       
   268 // ---------------------------------------------------------------------------
       
   269 // 
       
   270 // ---------------------------------------------------------------------------
       
   271 //
       
   272 TInt RWlanHeap::Available(TInt& aBiggestBlock) const
       
   273     {
       
   274 
       
   275     TInt total = 0;
       
   276     TInt max = 0;
       
   277     SCell* pC = iFree.next;
       
   278     for (; pC; pC=pC->next)
       
   279         {
       
   280         TInt l = pC->len - EAllocCellSize;
       
   281         if (l > max)
       
   282             {
       
   283             max = l;
       
   284             }
       
   285         total += l;
       
   286         }
       
   287     aBiggestBlock = max;
       
   288     return total;
       
   289     }
       
   290 
       
   291