Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 
     19 /*! \file oscl_mem_audit.cpp
     20     \brief This file contains the implementation of MM_Audit class
     21 */
     22 #include "osclconfig_memory.h"
     23 
     24 #if (!OSCL_BYPASS_MEMMGT)
     25 
     26 #include "oscl_types.h"
     27 #include "oscl_mem.h"
     28 #include "oscl_mem_audit.h"
     29 #include "oscl_mem_audit_internals.h"
     30 #include "oscl_assert.h"
     31 #include "oscl_stdstring.h"
     32 
     33 
     34 #if MM_AUDIT_FENCE_SUPPORT
     35 const uint32 PRE_PAD_SIZE = sizeof(MM_AllocBlockFence);
     36 const uint32 POST_FENCE_SIZE = sizeof(MM_AllocBlockFence);
     37 #else
     38 const uint32 PRE_PAD_SIZE = 0;
     39 const uint32 POST_FENCE_SIZE = 0;
     40 #endif
     41 
     42 const uint32 CONTROL_HEADER_SIZE = sizeof(MM_AllocBlockHdr);
     43 const uint32 BLOCK_HDR_SIZE = CONTROL_HEADER_SIZE + PRE_PAD_SIZE;
     44 const uint32 BLOCK_OVERHEAD_SIZE = BLOCK_HDR_SIZE + POST_FENCE_SIZE;
     45 
     46 
     47 /**
     48  * MM_Audit_Imp constructor and descontructor
     49  */
     50 
     51 /* ======================================================================== */
     52 /*  Function : MM_Audit()                                                   */
     53 /*  Date     : 10/08/2002                                                   */
     54 /*  Purpose  : Constructor, create the root node in statistics table        */
     55 /*  In/out   :                                                              */
     56 /*  Return   :                                                              */
     57 /*  Modified :                                                              */
     58 /* ======================================================================== */
     59 
     60 const char root_tag[] = "";
     61 
     62 MM_Audit_Imp::MM_Audit_Imp()
     63 {
     64     mpCurrAllocNode = mpAllocNode = NULL;
     65     mNumAllocNodes = 0;
     66 
     67     prefill_pattern = DEFAULT_PREFILL_PATTERN;
     68     postfill_pattern = DEFAULT_POSTFILL_PATTERN;
     69 
     70     mpStatsNode = NULL;
     71     mnAllocNum = 0;
     72     mnMaxTagLevel = 10;
     73 
     74     mm_audit_per_block_overhead = 0;
     75     mm_audit_stats_overhead = 0;
     76 
     77     mode = DEFAULT_MM_AUDIT_MODE;
     78 
     79     /* create root node in memory statistics table */
     80     mpStatsNode = createStatsNode(root_tag);
     81 }
     82 
     83 /* ======================================================================== */
     84 /*  Function : ~MM_Audit()                                                  */
     85 /*  Date     : 10/08/2002                                                   */
     86 /*  Purpose  : destructor, remove all the nodes in allocation and           */
     87 /*             statistics table                                             */
     88 /*  In/out   :                                                              */
     89 /*  Return   :                                                              */
     90 /*  Modified :                                                              */
     91 /* ======================================================================== */
     92 
     93 MM_Audit_Imp::~MM_Audit_Imp()
     94 {
     95 
     96 #if MM_AUDIT_ALLOC_NODE_SUPPORT
     97     /**
     98      * Delete all the allocation nodes
     99      */
    100     removeALLAllocNodes();
    101     mpAllocNode = mpCurrAllocNode = NULL;
    102     mnAllocNum = 0;
    103 #endif
    104 
    105     /**
    106      * Delete all the statistics nodes
    107      */
    108     mpStatsNode = NULL;
    109 
    110     mTagTree.clear();
    111 }
    112 
    113 
    114 /*
    115 * ===================== API FUNCTIONS: MM_xxx() ==================================
    116 */
    117 
    118 /* ============================================================================ */
    119 /*  Function : MM_allocate()                                                    */
    120 /*  Date     : 10/08/2002                                                       */
    121 /*  Purpose  : API for a memory allocation attempt: create a new node in        */
    122 /*             allocation table and update/create the corresponding node in     */
    123 /*             statistics table                                                 */
    124 /*  In/out   : all parameters are input                                         */
    125 /*  Return   : memory pointer, if something is wrong, the pointer will be NULL  */
    126 /*  Modified :                                                                  */
    127 /* ============================================================================ */
    128 
    129 OSCL_EXPORT_REF void* MM_Audit_Imp::MM_allocate(const OsclMemStatsNode* pInStatsNode,
    130         uint32 sizeIn,
    131         const char *pFileName,
    132         uint32 lineNumber,
    133         bool allocNodeTracking)
    134 {
    135 
    136 #if defined(DEBUG_ENABLE)
    137     PVUStackTrace();
    138     if (pFileName)
    139     {
    140         printf("In MM_allocate, nBytes %d, file_name is %s, line_num is %d\n", sizeIn, pFileName, lineNumber);
    141     }
    142     else
    143     {
    144         printf("In MM_allocate with tag %s operator, nBytes %d\n", sizeIn);
    145     }
    146 #endif
    147 
    148     MMAuditUint8AutoPtr pMem;
    149     void  *pMem_out = NULL;
    150 
    151 #if (MM_AUDIT_ALLOC_NODE_SUPPORT && MM_AUDIT_INCLUDE_ALL_HEAP_VALIDATION)
    152     if (mode & MM_AUDIT_VALIDATE_ALL_HEAP_FLAG)
    153     {
    154         validate_all_heap();
    155     }
    156 #endif
    157 
    158     OsclMemStatsNode* pStatsNode;
    159     if (pInStatsNode)
    160     {
    161         // remove "constness" of the stats node so it can be updated.
    162         pStatsNode = const_cast<OsclMemStatsNode*>(pInStatsNode);
    163     }
    164     else
    165     {
    166         pStatsNode = mpStatsNode; // set to the root node.
    167     }
    168 
    169     uint32 full_size = sizeIn + BLOCK_OVERHEAD_SIZE;
    170 
    171 #if MM_AUDIT_FAILURE_SIMULATION_SUPPORT
    172     if (!isSetFailure(pStatsNode))
    173     {
    174         pMem.allocate(full_size);
    175     }
    176 #else
    177     if (full_size > sizeIn)
    178     {
    179         pMem.allocate(full_size);
    180     }
    181 #endif
    182 
    183     if (!pMem.get())
    184     {
    185         updateStatsNodeInFailure(pStatsNode);
    186         return NULL;
    187     }
    188 
    189 
    190     MM_AllocNode* pAllocNode = NULL;
    191 #if MM_AUDIT_ALLOC_NODE_SUPPORT
    192 
    193     if ((mode & MM_AUDIT_ALLOC_NODE_ENABLE_FLAG) || allocNodeTracking ||
    194             (sizeIn & MM_AllocBlockHdr::ALLOC_NODE_FLAG))
    195     {
    196         if ((pAllocNode = addAllocNode((void *)pMem.get(), sizeIn, pStatsNode, pFileName, lineNumber)) == NULL)
    197         {
    198             updateStatsNodeInFailure(pStatsNode);
    199             return NULL;
    200         }
    201     }
    202 #endif
    203 
    204     // now write the header to the block
    205     MM_AllocBlockHdr *block_hdr =
    206         static_cast<MM_AllocBlockHdr *>(static_cast<void*>(pMem.get()));
    207     block_hdr->size = sizeIn;
    208     if (pAllocNode)
    209     {
    210         block_hdr->setAllocNodeFlag();
    211         block_hdr->pNode = pAllocNode;
    212     }
    213     else
    214     {
    215         block_hdr->pNode =  pStatsNode;
    216     }
    217 
    218     /**
    219     * Save the root audit node pointer in the header.
    220     * This pointer will be used when the block is deallocated.
    221     */
    222     OsclAuditCB audit;
    223     OsclMemInit(audit);
    224     block_hdr->pRootNode = audit.pAudit;
    225 
    226 #if MM_AUDIT_FILL_SUPPORT
    227     if ((mode & MM_AUDIT_PREFILL_FLAG))
    228     {
    229         oscl_memset(pMem.get() + BLOCK_HDR_SIZE, prefill_pattern, sizeIn);
    230     }
    231 #endif
    232 
    233 
    234 #if MM_AUDIT_FENCE_SUPPORT
    235     /* fill the pre-fence */
    236     MM_AllocBlockFence *pFence =
    237         static_cast<MM_AllocBlockFence*>(static_cast<void*>(pMem.get() +
    238                                          CONTROL_HEADER_SIZE));
    239     pFence->fill_fence();
    240 
    241     /* fill the post-fence */
    242     uint32 post_fence_offset = sizeIn + BLOCK_HDR_SIZE;
    243     pFence =
    244         static_cast<MM_AllocBlockFence*>(static_cast<void*>(pMem.get() +
    245                                          post_fence_offset));
    246     pFence->fill_fence();
    247 #endif
    248 
    249 
    250     /* 8-byte alignment */
    251     pMem_out = pMem.get() + BLOCK_HDR_SIZE;
    252     MM_Stats_t delta;
    253     delta.numBytes = sizeIn;
    254     delta.numAllocs = 1;
    255     delta.numAllocFails = 0;
    256     updateStatsNode(pStatsNode, delta, true);
    257 
    258     pMem.release(); // release so it doesn't free up memory on exit
    259 
    260     // account for the per-block overhead
    261     mm_audit_per_block_overhead += BLOCK_OVERHEAD_SIZE;
    262     return pMem_out;
    263 
    264 }
    265 
    266 /* ============================================================================ */
    267 /*  Function : MM_deallocate()                                                  */
    268 /*  Date     : 10/08/2002                                                       */
    269 /*  Purpose  : API for a memory de-allocation attempt: remove a node in         */
    270 /*             allocation table and update the corresponding node in            */
    271 /*             statistics table                                                 */
    272 /*  In/out   : all parameters are input                                         */
    273 /*  Return   :                                                                  */
    274 /*  Modified :                                                                  */
    275 /* ============================================================================ */
    276 
    277 OSCL_EXPORT_REF bool  MM_Audit_Imp::MM_deallocate(void *pMemBlockIn)
    278 {
    279     if (!pMemBlockIn)  return false;
    280 
    281     if (mpStatsNode == NULL ||
    282             (mpStatsNode && mpStatsNode->pMMStats && mpStatsNode->pMMStats->peakNumBytes == 0)) /* No actual allocation happens */
    283     {
    284         return true;
    285     }
    286 
    287 #if (MM_AUDIT_ALLOC_NODE_SUPPORT && MM_AUDIT_INCLUDE_ALL_HEAP_VALIDATION)
    288     if (mode & MM_AUDIT_VALIDATE_ALL_HEAP_FLAG)
    289     {
    290         validate_all_heap();
    291     }
    292 #endif
    293 
    294     bool status = true;
    295 #if MM_AUDIT_VALIDATE_BLOCK
    296     if (mode & MM_AUDIT_VALIDATE_ON_FREE_FLAG)
    297     {
    298         if (!validate(pMemBlockIn))
    299         {
    300             return false;
    301         }
    302     }
    303 #endif
    304 
    305     uint8 *pMem = static_cast<uint8 *>(pMemBlockIn);
    306     pMem -= BLOCK_HDR_SIZE;
    307 
    308     OsclMemStatsNode *pStatsNode = NULL;
    309     MM_AllocBlockHdr *pMemBlockHdr =
    310         static_cast<MM_AllocBlockHdr*>(static_cast<void*>(pMem));
    311     uint32 size = pMemBlockHdr->size;
    312 
    313 #if MM_AUDIT_ALLOC_NODE_SUPPORT
    314     if (size & MM_AllocBlockHdr::ALLOC_NODE_FLAG)
    315     {
    316         pStatsNode = removeAllocNode((void *)pMem, size);
    317         OSCL_ASSERT(pStatsNode);
    318     }
    319 #endif
    320 
    321     if (!pStatsNode)
    322     {
    323         pStatsNode = static_cast<OsclMemStatsNode*>(pMemBlockHdr->pNode);
    324     }
    325     /**
    326      * 3/1. update the node in memory statistics table
    327      */
    328     MM_Stats_t delta;
    329     delta.numAllocs = 1;
    330     delta.numBytes = size;
    331     delta.numAllocFails = 0;
    332     status = updateStatsNode(pStatsNode, delta, false);
    333 
    334 #if MM_AUDIT_FILL_SUPPORT
    335     if ((mode & MM_AUDIT_POSTFILL_FLAG))
    336     {
    337         oscl_memset(pMem + BLOCK_HDR_SIZE, postfill_pattern, size);
    338     }
    339 #endif
    340 
    341 
    342     MMAuditUint8AutoPtr::deallocate(pMem);
    343 
    344     // account for the per-block overhead
    345     mm_audit_per_block_overhead -= BLOCK_OVERHEAD_SIZE;
    346 
    347 
    348     return status;
    349 }
    350 
    351 
    352 /* ============================================================================ */
    353 /*  Function : MM_GetTreeNodes()                                                */
    354 /*  Date     : 10/31/2002                                                       */
    355 /*  Purpose  : API to get the number of tree nodes including the tag node and   */
    356 /*             its subtree                                                      */
    357 /*  In/out   : all parameters are input                                         */
    358 /*  Return   : 0 means no tag node ; >0 means the number of tree nodes          */
    359 /*  Modified :                                                                  */
    360 /* ============================================================================ */
    361 
    362 OSCL_EXPORT_REF uint32 MM_Audit_Imp::MM_GetTreeNodes(const char *  tagIn)
    363 {
    364     int32 count = 0;
    365 
    366     MMAuditCharAutoPtr tag;
    367     makeValidTag(tagIn, tag); //tagIn = NULL means root tag
    368     OsclTagTreeType::iterator iter = mTagTree.find(tag.get());
    369 
    370     if (iter != mTagTree.end())
    371     {
    372         count++; //to account for the parent
    373         count = iter->children.size();
    374     }
    375     return ((uint32)count);
    376 }
    377 
    378 
    379 
    380 /* ================================================================================ */
    381 /*  Function : MM_GetStats()                                                        */
    382 /*  Date     : 10/08/2002                                                           */
    383 /*  Purpose  : API to get memory statistics through context string(tag)             */
    384 /*  In/out   : all parameters are input                                             */
    385 /*  Return   : the statistics (pointer) for the current tag node                    */
    386 /*             if something is wrong, return NULL                                   */
    387 /*  Modified :                                                                      */
    388 /* ================================================================================ */
    389 
    390 
    391 OSCL_EXPORT_REF MM_Stats_t* MM_Audit_Imp::MM_GetStats(const char * const  tagIn)
    392 {
    393     MM_Stats_t *pMMStats = NULL;
    394     MMAuditCharAutoPtr tag;
    395     makeValidTag(tagIn, tag); //tagIn = NULL means root tag
    396     OsclTagTreeType::iterator iter = mTagTree.find(tag.get());
    397 
    398     if (iter != mTagTree.end())
    399     {
    400         /* Got it! */
    401         OsclMemStatsNode *pStatsNode = (iter->value).get();
    402         if (pStatsNode)
    403         {
    404             pMMStats = pStatsNode->pMMStats;
    405         }
    406     }
    407     return pMMStats;
    408 }
    409 
    410 
    411 OSCL_EXPORT_REF uint32 MM_Audit_Imp::MM_GetStatsInDepth(const char *tagIn,
    412         MM_Stats_CB *array_ptr,
    413         uint32 max_nodes)
    414 {
    415     uint32 curr_array_index = 0;
    416     populateChildren(tagIn, array_ptr, curr_array_index, max_nodes);
    417     return (curr_array_index);
    418 }
    419 
    420 
    421 /* ============================================================================ */
    422 /*  Function : getNodeChildren()                                                */
    423 /*  Date     : 10/08/2002                                                       */
    424 /*  Purpose  : recursive function to go throught each child node for the        */
    425 /*             current node and counter it                                      */
    426 /*  In/out   : all parameters are input                                         */
    427 /*  Return   :                                                                  */
    428 /*  Modified :                                                                  */
    429 /* ============================================================================ */
    430 
    431 void MM_Audit_Imp::populateChildren(const char *tagIn,
    432                                     MM_Stats_CB *array_ptr,
    433                                     uint32 &curr_array_index,
    434                                     uint32 max_nodes)
    435 {
    436     MMAuditCharAutoPtr tag;
    437     makeValidTag(tagIn, tag); //tagIn = NULL means root tag
    438     OsclTagTreeType::iterator miter = mTagTree.find(tag.get());
    439 
    440     if (curr_array_index > max_nodes)
    441     {
    442         return;
    443     }
    444 
    445     if (miter != mTagTree.end() && max_nodes > 0)
    446     {
    447         uint32 num_children = miter->children.size();
    448 
    449         miter->sort_children();
    450 
    451         array_ptr[curr_array_index].num_child_nodes = num_children;
    452 
    453         for (uint32 i = 0; i < num_children; i++)
    454         {
    455             array_ptr[curr_array_index].tag = (miter->tag).tag;
    456 
    457             OsclMemStatsNode *pStatsNode = (miter->value).get();
    458             if (pStatsNode)
    459             {
    460                 array_ptr[curr_array_index].pStats = pStatsNode->pMMStats;
    461             }
    462             curr_array_index++;
    463 
    464             if (curr_array_index > max_nodes)
    465             {
    466                 return;
    467             }
    468         }
    469 
    470         /* access its children nodes */
    471         if (!miter->children.empty())
    472         {
    473             /* recursive search */
    474             for (uint32 i = 0; i < num_children; i++)
    475             {
    476                 populateChildren((miter->children[i]->tag).tag,
    477                                  array_ptr,
    478                                  curr_array_index,
    479                                  max_nodes);
    480             }
    481         }
    482     }
    483 
    484     return;
    485 }
    486 
    487 /* ============================================================================ */
    488 /*  Function : MM_GetTag()                                                      */
    489 /*  Date     : 10/08/2002                                                       */
    490 /*  Purpose  : API to get an StatsNode or creates one if it doesn't exist */
    491 /*  In/out   : all parameters are input                                         */
    492 /*  Return   : pointer to OsclMemStatsNode if operation succeeds, NULL otherwise                                        */
    493 /*  Modified :                                                                  */
    494 /* ============================================================================ */
    495 
    496 OSCL_EXPORT_REF const OsclMemStatsNode* MM_Audit_Imp::MM_GetTagNode(const char * tagIn)
    497 {
    498     MMAuditCharAutoPtr tag;
    499     makeValidTag(tagIn, tag); //tagIn = NULL means root tag
    500     OsclTagTreeType::iterator iter = mTagTree.find(tag.get());
    501     if (iter != mTagTree.end())
    502         return ((iter->value).get());
    503     else
    504         return createStatsNode(tag.get()); /* create a new empty node */
    505 }
    506 
    507 /* ============================================================================ */
    508 /*  Function : MM_GetTag()                                                      */
    509 /*  Date     : 10/08/2002                                                       */
    510 /*  Purpose  : API to get an existing node  */
    511 /*  In/out   : all parameters are input                                         */
    512 /*  Return   : pointer to OsclMemStatsNode if operation succeeds, NULL otherwise                                        */
    513 /*  Modified :                                                                  */
    514 /* ============================================================================ */
    515 
    516 OSCL_EXPORT_REF const OsclMemStatsNode* MM_Audit_Imp::MM_GetExistingTag(const char * tagIn)
    517 {
    518     MMAuditCharAutoPtr tag;
    519     makeValidTag(tagIn, tag); //tagIn = NULL means root tag
    520     OsclTagTreeType::iterator iter = mTagTree.find(tag.get());
    521     if (iter != mTagTree.end())
    522         return ((iter->value).get());
    523     else
    524         return NULL;
    525 }
    526 
    527 
    528 
    529 
    530 /* ============================================================================ */
    531 /*  Function : MM_Validate()                                                    */
    532 /*  Date     : 10/08/2002                                                       */
    533 /*  Purpose  : API to check the input pointer is a valid pointer to a chunk of  */
    534 /*             memory                                                           */
    535 /*  In/out   : all parameters are input                                         */
    536 /*  Return   :                                                                  */
    537 /*  Modified :                                                                  */
    538 /* ============================================================================ */
    539 
    540 OSCL_EXPORT_REF bool MM_Audit_Imp::MM_Validate(const void *ptrIn)
    541 {
    542     bool status = validate(const_cast<void*>(ptrIn));
    543     return status;
    544 }
    545 
    546 /* ============================================================================ */
    547 /*  Function : MM_SetTagLevel()                                                 */
    548 /*  Date     : 10/08/2002                                                       */
    549 /*  Purpose  : API to set the maximum tag level,i.e. tag level for a.b.c.d = 4  */
    550 /*  In/out   : all parameters are input                                         */
    551 /*  Return   :                                                                  */
    552 /*  Modified :                                                                  */
    553 /* ============================================================================ */
    554 
    555 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetTagLevel(uint32 level)
    556 {
    557     if (level >= 1) mnMaxTagLevel = level;
    558 }
    559 
    560 
    561 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetMode(uint32 in_mode)
    562 {
    563     mode = in_mode;
    564 }
    565 
    566 
    567 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetPrefillPattern(uint8 pattern)
    568 {
    569     prefill_pattern = pattern;
    570 }
    571 
    572 
    573 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetPostfillPattern(uint8 pattern)
    574 {
    575     postfill_pattern = pattern;
    576 }
    577 
    578 OSCL_EXPORT_REF MM_AllocQueryInfo* MM_Audit_Imp::MM_CreateAllocNodeInfo(uint32 array_size)
    579 {
    580     return(MM_AllocQueryInfo*)_oscl_malloc(array_size*sizeof(MM_AllocQueryInfo));
    581 }
    582 
    583 OSCL_EXPORT_REF void MM_Audit_Imp::MM_ReleaseAllocNodeInfo(MM_AllocQueryInfo* output_array)
    584 {
    585     _oscl_free(output_array);
    586 }
    587 
    588 OSCL_EXPORT_REF uint32 MM_Audit_Imp::MM_GetAllocNodeInfo(MM_AllocQueryInfo* output_array,
    589         uint32 max_array_size, uint32 offset)
    590 {
    591     uint32 num_nodes = 0;
    592 
    593     if (!output_array)
    594     {
    595         return 0;
    596     };
    597 
    598 
    599     if (offset >= mNumAllocNodes)
    600     {
    601         return 0;
    602     }
    603 
    604     MM_AllocNode *pAllocNode = mpAllocNode;
    605 
    606     // skip the leading nodes
    607     uint32 ii;
    608     for (ii = 0; pAllocNode && ii < offset; ++ii, pAllocNode = pAllocNode->pNext)
    609     {
    610     }
    611 
    612     if (ii != offset)
    613     {
    614         return 0;
    615     }
    616 
    617     MM_AllocQueryInfo* pOutNode = output_array;
    618 
    619     while (pAllocNode && (num_nodes < max_array_size))
    620     {
    621 
    622         pOutNode->allocNum = pAllocNode->pAllocInfo->allocNum;
    623         pOutNode->lineNo = pAllocNode->pAllocInfo->lineNo;
    624         pOutNode->size = pAllocNode->pAllocInfo->size;
    625         pOutNode->pMemBlock = pAllocNode->pAllocInfo->pMemBlock;
    626         pOutNode->size = pAllocNode->pAllocInfo->size;
    627 
    628         if (pAllocNode->pAllocInfo->pFileName)
    629         {
    630             oscl_strncpy(pOutNode->fileName, pAllocNode->pAllocInfo->pFileName,
    631                          oscl_strlen(pAllocNode->pAllocInfo->pFileName) + 1);
    632             pOutNode->fileName[MM_ALLOC_MAX_QUERY_FILENAME_LEN-1] = '\0';
    633         }
    634         else
    635         {
    636             pOutNode->fileName[0] = '\0';
    637         }
    638 
    639         if (pAllocNode->pAllocInfo->pStatsNode->tag)
    640         {
    641             oscl_strncpy(pOutNode->tag, pAllocNode->pAllocInfo->pStatsNode->tag,
    642                          oscl_strlen(pAllocNode->pAllocInfo->pStatsNode->tag) + 1);
    643             pOutNode->tag[MM_ALLOC_MAX_QUERY_TAG_LEN-1] = '\0';
    644         }
    645         else
    646         {
    647             pOutNode->tag[0] = '\0';
    648         }
    649 
    650         ++num_nodes;
    651         ++pOutNode;
    652         pAllocNode = pAllocNode->pNext;
    653     }
    654     return num_nodes;
    655 }
    656 
    657 /* ============================================================================ */
    658 /*  Function : MM_SetFailurePoint()                                             */
    659 /*  Date     : 11/05/2002                                                       */
    660 /*  Purpose  : API to insert allocation failure deterministically according to  */
    661 /*             allocation number associated with tag                            */
    662 /*  In/out   : all parameters are input                                         */
    663 /*  Return   : true if operation succeeds                                       */
    664 /*  Modified :                                                                  */
    665 /* ============================================================================ */
    666 
    667 OSCL_EXPORT_REF bool MM_Audit_Imp::MM_SetFailurePoint(const char * tagIn, uint32 alloc_number)
    668 {
    669     if (alloc_number == 0) return false;
    670 
    671     bool status = true;
    672     MMAuditCharAutoPtr tag;
    673     makeValidTag(tagIn, tag); //tagIn = NULL means root tag
    674     OsclTagTreeType::iterator miter = mTagTree.find(tag.get());
    675 
    676     if (miter != mTagTree.end())
    677     {
    678         /* found */
    679         OsclMemStatsNode *pStatsNode = (miter->value).get();
    680 
    681         if (pStatsNode == NULL || pStatsNode->pMMFIParam == NULL)
    682         {
    683             return false;
    684         }
    685         pStatsNode->pMMFIParam->nAllocNum = alloc_number;
    686     }
    687     else
    688     {
    689         /* Needs to create a new node */
    690         OsclMemStatsNode *pStatsNode = createStatsNode(tag.get());
    691         if (pStatsNode == NULL || pStatsNode->pMMFIParam == NULL)
    692         {
    693             return false;
    694         }
    695         pStatsNode->pMMFIParam->nAllocNum = alloc_number;
    696     }
    697 
    698     return status;
    699 }
    700 
    701 
    702 /* ============================================================================ */
    703 /*  Function : MM_UnsetFailurePoint()                                           */
    704 /*  Date     : 11/05/2002                                                       */
    705 /*  Purpose  : API to cancel the allocation failure point associated with tag   */
    706 /*  In/out   : all parameters are input                                         */
    707 /*  Return   :                                                                  */
    708 /*  Modified :                                                                  */
    709 /* ============================================================================ */
    710 
    711 OSCL_EXPORT_REF void MM_Audit_Imp::MM_UnsetFailurePoint(const char * tagIn)
    712 {
    713     MMAuditCharAutoPtr tag;
    714     makeValidTag(tagIn, tag); //tagIn = NULL means root tag
    715     OsclTagTreeType::iterator miter = mTagTree.find(tag.get());
    716 
    717     if (miter != mTagTree.end())
    718     {
    719         /* found */
    720         OsclMemStatsNode *pStatsNode = (miter->value).get();
    721         if (pStatsNode && pStatsNode->pMMFIParam)
    722         {
    723             pStatsNode->pMMFIParam->nAllocNum = 0;
    724         }
    725     }
    726 }
    727 
    728 
    729 /*
    730 * ===================== PRIVATE (SUPPORTING) FUNCTIONS ===========================
    731 */
    732 
    733 
    734 #if MM_AUDIT_ALLOC_NODE_SUPPORT
    735 /* ============================================================================ */
    736 /*  Function : addAllocNode()                                                   */
    737 /*  Date     : 10/08/2002                                                       */
    738 /*  Purpose  : add a node in memory allocation table triggered by an allocation */
    739 /*             attempt, i.e. MM_allocate(); then update/creat the corresponding */
    740 /*             node in memory statistics table                                  */
    741 /*  In/out   : all parameters are input                                         */
    742 /*  Return   : true if operation succeeds                                       */
    743 /*  Modified :                                                                  */
    744 /* ============================================================================ */
    745 
    746 MM_AllocNode* MM_Audit_Imp::addAllocNode(void *pMemBlockIn, uint32 sizeIn,
    747         OsclMemStatsNode *pStatsNode,
    748         const char *pFileName, uint32 lineNumber
    749                                         )
    750 {
    751     uint32 tmp_overhead_size = 0;
    752 
    753     /**
    754      * 1. allocate memory for a new node
    755      */
    756 
    757     MM_AllocNodeAutoPtr currAllocAutoPtr(new MM_AllocNode);
    758     if (! currAllocAutoPtr.get())
    759     {
    760         return NULL;
    761     }
    762     tmp_overhead_size += sizeof(MM_AllocNode);
    763 
    764     MM_AllocInfo* pAllocInfo = currAllocAutoPtr->pAllocInfo = new MM_AllocInfo;
    765     if (pAllocInfo == NULL)
    766     {
    767         return NULL;
    768     }
    769     tmp_overhead_size += sizeof(MM_AllocInfo);
    770 
    771     // allocate space for the filename in AllocInfo
    772     if (pFileName)
    773     {
    774         int len = oscl_strlen(pFileName);
    775         Oscl_TAlloc<char, OsclMemBasicAllocator> charAlloc;
    776         if ((pAllocInfo->pFileName =
    777                     charAlloc.allocate(len + 1)) == NULL)
    778         {
    779             return NULL;
    780         }
    781         oscl_strncpy(const_cast<char*>(pAllocInfo->pFileName), pFileName, oscl_strlen(pFileName) + 1);
    782         tmp_overhead_size += len + 1;
    783     }
    784 
    785     pAllocInfo->allocNum  = mnAllocNum;
    786 
    787     //To find memory leaks by allocation number, put a debug breakpoint here, like this:
    788     //if(mnAllocNum==113)
    789     //{
    790     //  mnAllocNum++;
    791     //  mnAllocNum--;
    792     //}
    793 
    794     //To find allocations with a NULL filename, put a debug breakpoint here, like this:
    795     //if(pFileName==NULL)
    796     //{
    797     //  mnAllocNum++;
    798     //  mnAllocNum--;
    799     //}
    800 
    801     mnAllocNum++;
    802 
    803     pAllocInfo->pMemBlock = pMemBlockIn;
    804     pAllocInfo->size      = sizeIn;
    805     pAllocInfo->lineNo  = lineNumber;
    806     pAllocInfo->pStatsNode = pStatsNode;
    807 
    808     if (!mpCurrAllocNode)  /* First node */
    809     {
    810         /* mpAllocNode always represents the very first node */
    811         mpAllocNode = mpCurrAllocNode = currAllocAutoPtr.release();
    812     }
    813     else
    814     {
    815         OSCL_ASSERT(!mpCurrAllocNode->pNext);
    816         mpCurrAllocNode->pNext = currAllocAutoPtr.release();
    817         currAllocAutoPtr->pPrev = mpCurrAllocNode;
    818         mpCurrAllocNode = mpCurrAllocNode->pNext;
    819     }
    820 
    821 
    822     /* increment the list counter */
    823     ++mNumAllocNodes;
    824 
    825     mm_audit_per_block_overhead += tmp_overhead_size;
    826     return mpCurrAllocNode;
    827 
    828 }
    829 
    830 /* ============================================================================ */
    831 /*  Function : removeAllocNode()                                                */
    832 /*  Date     : 10/08/2002                                                       */
    833 /*  Purpose  : remove a node in memory allocation table triggered by an         */
    834 /*             de-allocationattempt, i.e. MM_deallocate()                       */
    835 /*  In/out   : all parameters are input                                         */
    836 /*  Return   : true if operation succeeds                                       */
    837 /*  Modified :                                                                  */
    838 /* ============================================================================ */
    839 
    840 OsclMemStatsNode* MM_Audit_Imp::removeAllocNode(void *pMemBlockIn, uint32& size)
    841 {
    842 
    843     if (pMemBlockIn == NULL)
    844         return NULL;
    845 
    846     OsclMemStatsNode *pStatsNode = NULL;
    847 
    848     OSCL_ASSERT(mpAllocNode);
    849     OSCL_ASSERT(mpCurrAllocNode);
    850     OSCL_ASSERT(mNumAllocNodes);
    851 
    852     /* take the allocation node pointer from the control info header */
    853     MM_AllocBlockHdr *pMemBlockHdr = static_cast<MM_AllocBlockHdr*>(pMemBlockIn);
    854     MM_AllocNode *pAllocNode = static_cast<MM_AllocNode*>(pMemBlockHdr->pNode);
    855     if (!pAllocNode)  return NULL;
    856 
    857     /*
    858      * 1. remove the current node from the list
    859      */
    860     if (pAllocNode == mpAllocNode)
    861     {
    862         /* head of the list*/
    863         mpAllocNode = mpAllocNode->pNext;
    864         if (mpAllocNode)
    865         {
    866             mpAllocNode->pPrev = NULL;
    867         }
    868         else
    869         {
    870             // list is empty
    871             mpCurrAllocNode = mpAllocNode = NULL;
    872         }
    873     }
    874     else if (pAllocNode == mpCurrAllocNode) /* end of the list */
    875     {
    876         mpCurrAllocNode = mpCurrAllocNode->pPrev;
    877         if (mpCurrAllocNode)
    878         {
    879             mpCurrAllocNode->pNext = NULL;
    880         }
    881         else
    882         {
    883             // list is empty
    884             mpCurrAllocNode = mpAllocNode = NULL;
    885         }
    886     }
    887     else   /* somewhere in the list */
    888     {
    889         MM_AllocNode *pPrevNode = pAllocNode->pPrev;
    890         MM_AllocNode *pNextNode = pAllocNode->pNext;
    891 
    892         OSCL_ASSERT(pPrevNode && pNextNode);
    893 
    894         pPrevNode->pNext = pNextNode;
    895         pNextNode->pPrev = pPrevNode;
    896     }
    897 
    898     /**
    899      * 2. free the memory for the current node
    900      */
    901     OSCL_ASSERT(pAllocNode->pAllocInfo);
    902     pStatsNode = pAllocNode->pAllocInfo->pStatsNode;
    903     size = pAllocNode->pAllocInfo->size;
    904 
    905     // adjust the overhead accounting
    906     uint32 filename_len = (pAllocNode->pAllocInfo->pFileName) ? oscl_strlen(pAllocNode->pAllocInfo->pFileName) + 1 : 0;
    907     mm_audit_per_block_overhead -= sizeof(MM_AllocNode) + sizeof(MM_AllocInfo) +
    908                                    filename_len;
    909 
    910 
    911     OSCL_DELETE(pAllocNode);
    912 
    913 
    914 
    915     /*
    916      * decrement the list counter
    917      */
    918     --mNumAllocNodes;
    919 
    920 
    921 
    922 
    923     return pStatsNode;
    924 
    925 }
    926 
    927 /* ============================================================================ */
    928 /*  Function : removeALLAllocNodes()                                            */
    929 /*  Date     : 10/08/2002                                                       */
    930 /*  Purpose  : remove all the nodes in memory allocation table needed in        */
    931 /*             destructor                                                       */
    932 /*  In/out   :                                                                  */
    933 /*  Return   :                                                                  */
    934 /*  Modified :                                                                  */
    935 /* ============================================================================ */
    936 
    937 void MM_Audit_Imp::removeALLAllocNodes()
    938 {
    939 
    940     while (mpCurrAllocNode)
    941     {
    942         MM_AllocNode *pTmpNode = mpCurrAllocNode;
    943         mpCurrAllocNode = mpCurrAllocNode->pPrev;
    944         if (mpCurrAllocNode)
    945             mpCurrAllocNode->pNext = NULL;
    946         --mNumAllocNodes;
    947         OSCL_DELETE(pTmpNode);
    948     }
    949 }
    950 
    951 
    952 bool MM_Audit_Imp::validate_all_heap()
    953 {
    954 
    955     // walk the list of allocated nodes
    956     MM_AllocNode *ptr = mpAllocNode;
    957 
    958     if (!ptr)
    959     {
    960         OSCL_ASSERT(mNumAllocNodes == 0);
    961         return true;
    962     }
    963 
    964     uint32 counter;
    965 
    966     OSCL_ASSERT(ptr->pPrev == NULL);
    967     for (counter = 0; ptr; ptr = ptr->pNext, ++counter)
    968     {
    969         MM_AllocBlockHdr *pMemBlockHdr = static_cast<MM_AllocBlockHdr*>(ptr->pAllocInfo->pMemBlock);
    970 
    971         OSCL_ASSERT(pMemBlockHdr->pNode == (void *)ptr);
    972         if (ptr->pNext)
    973         {
    974             OSCL_ASSERT(ptr->pNext->pPrev == ptr);
    975         }
    976         else
    977         {
    978             OSCL_ASSERT(ptr == mpCurrAllocNode);
    979         }
    980 
    981         uint8* pMem = static_cast<uint8*>(static_cast<void*>(pMemBlockHdr));
    982         pMem += BLOCK_HDR_SIZE;
    983         bool status = validate(pMem);
    984         OSCL_ASSERT(status);
    985         if (!status)
    986         {
    987             return false;
    988         }
    989     }
    990 
    991     OSCL_ASSERT(counter == mNumAllocNodes);
    992 
    993     return true;
    994 
    995 }
    996 
    997 
    998 #endif // #if MM_AUDIT_ALLOC_NODE_SUPPORT
    999 
   1000 /* ============================================================================ */
   1001 /*  Function : validate()                                                       */
   1002 /*  Date     : 11/05/2002                                                       */
   1003 /*  Purpose  : validate the input pointer to a chunk of memory                  */
   1004 /*  In/out   : input the memory pointer                     */
   1005 /*  Return   : true if operation succeeds                                       */
   1006 /*  Modified :                                                                  */
   1007 /* ============================================================================ */
   1008 
   1009 bool MM_Audit_Imp::validate(void *ptrIn)
   1010 {
   1011     if (!ptrIn) return false;
   1012 
   1013     uint8 *pMem = static_cast<uint8*>(const_cast<void*>(ptrIn));
   1014 
   1015     pMem -= BLOCK_HDR_SIZE;
   1016 
   1017     MM_AllocBlockHdr *pMemBlockHdr =
   1018         static_cast<MM_AllocBlockHdr*>((void *)pMem);
   1019 
   1020     OSCL_ASSERT(pMemBlockHdr->pNode);
   1021     if (!pMemBlockHdr->pNode)
   1022     {
   1023         return false;
   1024     }
   1025 
   1026 
   1027     OsclMemStatsNode *pStatsNode = NULL;
   1028 #if MM_AUDIT_ALLOC_NODE_SUPPORT
   1029 #if MM_AUDIT_FENCE_SUPPORT
   1030     uint32 size = pMemBlockHdr->size;
   1031 #endif
   1032     if (pMemBlockHdr->isAllocNodePtr())
   1033     {
   1034         MM_AllocNode *pAllocNode = NULL;
   1035         pAllocNode = static_cast<MM_AllocNode*>(pMemBlockHdr->pNode);
   1036         OSCL_ASSERT(pAllocNode->pAllocInfo);
   1037 #if MM_AUDIT_FENCE_SUPPORT
   1038         OSCL_ASSERT(((size ^ pAllocNode->pAllocInfo->size) & (~MM_AllocBlockHdr::ALLOC_NODE_FLAG)) == 0);
   1039         size = pAllocNode->pAllocInfo->size;
   1040 #endif
   1041         pStatsNode =  pAllocNode->pAllocInfo->pStatsNode;
   1042     }
   1043 #endif
   1044 
   1045     if (!pStatsNode)
   1046     {
   1047         // must be a stats node
   1048         pStatsNode = static_cast<OsclMemStatsNode*>(pMemBlockHdr->pNode);
   1049     }
   1050 
   1051     OSCL_ASSERT(pStatsNode->pMMStats);
   1052 
   1053 #if MM_AUDIT_FENCE_SUPPORT
   1054     bool status;
   1055 
   1056     // check the pre-fence
   1057     MM_AllocBlockFence *fence =
   1058         static_cast<MM_AllocBlockFence*>(static_cast<void*>(pMem +
   1059                                          CONTROL_HEADER_SIZE));
   1060     status = fence->check_fence();
   1061     if (!status)
   1062     {
   1063         OSCL_ASSERT(status);
   1064         return status;
   1065     }
   1066 
   1067     // check the post fence
   1068     fence =
   1069         static_cast<MM_AllocBlockFence*>(static_cast<void*>(pMem +
   1070                                          BLOCK_HDR_SIZE
   1071                                          + size));
   1072     status = fence->check_fence();
   1073     if (!status)
   1074     {
   1075         OSCL_ASSERT(status);
   1076         return status;
   1077     }
   1078 #endif
   1079 
   1080     return true;
   1081 }
   1082 
   1083 /** Retrieve the audit root pointer from within an allocation block*/
   1084 OsclMemAudit * MM_Audit_Imp::getAuditRoot(void *ptrIn)
   1085 {
   1086     if (!ptrIn) return false;
   1087 
   1088     uint8 *pMem = static_cast<uint8*>(const_cast<void*>(ptrIn));
   1089 
   1090     pMem -= BLOCK_HDR_SIZE;
   1091 
   1092     MM_AllocBlockHdr *pMemBlockHdr =
   1093         static_cast<MM_AllocBlockHdr*>((void *)pMem);
   1094 
   1095     return (OsclMemAudit*)pMemBlockHdr->pRootNode;
   1096 }
   1097 
   1098 uint32 MM_Audit_Imp::getSize(void *ptrIn)
   1099 {//get original allocation size.
   1100 
   1101     if (!ptrIn)
   1102         return 0;
   1103 
   1104     uint8 *pMem = static_cast<uint8*>(const_cast<void*>(ptrIn));
   1105 
   1106     pMem -= BLOCK_HDR_SIZE;
   1107 
   1108     MM_AllocBlockHdr *pMemBlockHdr = static_cast<MM_AllocBlockHdr*>((void *)pMem);
   1109 
   1110     //if it's an alloc node we have to strip out the alloc node bit
   1111     //from the size field.
   1112     if (pMemBlockHdr->isAllocNodePtr())
   1113     {
   1114         return pMemBlockHdr->size & ~MM_AllocBlockHdr::ALLOC_NODE_FLAG;
   1115     }
   1116     else
   1117     {
   1118         return pMemBlockHdr->size;
   1119     }
   1120 }
   1121 
   1122 
   1123 /* ============================================================================ */
   1124 /*  Function : createStatsNode()                                                */
   1125 /*  Date     : 10/08/2002                                                       */
   1126 /*  Purpose  : creat a new node in memory statistics table triggered by an      */
   1127 /*             allocation attempt,                                              */
   1128 /*  In/out   : all parameters are input                                         */
   1129 /*  Return   : true if operation succeeds                                       */
   1130 /*  Modified :                                                                  */
   1131 /* ============================================================================ */
   1132 
   1133 
   1134 OsclMemStatsNode* MM_Audit_Imp::createStatsNode(const char *  tagIn)
   1135 {
   1136     OsclTagTreeType::iterator iter;
   1137     MMAuditCharAutoPtr currentTag;
   1138     OsclMemStatsNode* statsNode;
   1139 
   1140     /* If the input tag already exists in the tagtree, it should have a pointer value of NULL */
   1141     OSCL_ASSERT((mTagTree.find(const_cast<char* const&>(tagIn)) == mTagTree.end()) ||
   1142                 (mTagTree.find(const_cast<char* const&>(tagIn)))->value.get() == 0);
   1143 
   1144     statsNode = new OsclMemStatsNode;
   1145     if (statsNode == NULL) return NULL;
   1146 
   1147     currentTag.allocate(oscl_strlen(tagIn) + 1);
   1148     if (!currentTag.get()) return NULL;
   1149     oscl_strncpy(currentTag.get(), tagIn, oscl_strlen(tagIn) + 1);
   1150     statsNode->tag = currentTag.release();
   1151 
   1152     if ((statsNode->pMMStats = new MM_Stats_t) == NULL) return NULL;
   1153 
   1154     if ((statsNode->pMMFIParam = new MM_FailInsertParam) == NULL) return NULL;
   1155 
   1156     OsclMemStatsNodeAutoPtr statsNodeAutoPtr(statsNode);
   1157 
   1158     // reassign ownership of the StatsNode to the tag tree
   1159     mTagTree[statsNodeAutoPtr->tag] = statsNodeAutoPtr;
   1160 
   1161     // account for the overhead memory
   1162     mm_audit_stats_overhead += sizeof(MM_Stats_t) +
   1163                                sizeof(MM_FailInsertParam) +
   1164                                sizeof(OsclMemStatsNode) +
   1165                                oscl_strlen(currentTag.get()) + 1;
   1166 
   1167     // how many levels deep is the node we just inserted?
   1168     iter = mTagTree.find(statsNodeAutoPtr->tag);
   1169     uint32 depth = iter->depth();
   1170 
   1171     // the tag tree will automatically create the parent, grandparent, etc.
   1172     // make sure each ancestor's stats node is initialized, i.e. initialize each ancestor
   1173     // until you reach one that is already initialized.
   1174     OsclTagTreeType::node_ptr parent = iter->parent;
   1175     for (uint32 ii = 0; ii < depth; ii++)
   1176     {
   1177 
   1178         OSCL_ASSERT(parent != 0);
   1179 
   1180         // if initialized then we're done
   1181         OsclMemStatsNode* tmpStatsNode = (parent->value).get();
   1182         if (tmpStatsNode != NULL) break;
   1183 
   1184         // create new stats node
   1185         tmpStatsNode = new OsclMemStatsNode;
   1186         if (tmpStatsNode == NULL) return NULL;
   1187 
   1188         // copy tag already created by the tag tree
   1189         currentTag.allocate(oscl_strlen(parent->tag.tag) + 1);
   1190         if (!currentTag.get()) return NULL;
   1191         oscl_strncpy(currentTag.get(), parent->tag.tag, oscl_strlen(parent->tag.tag) + 1);
   1192         tmpStatsNode->tag = currentTag.release();
   1193 
   1194         if ((tmpStatsNode->pMMStats = new MM_Stats_t) == NULL) return NULL;
   1195 
   1196         if ((tmpStatsNode->pMMFIParam = new MM_FailInsertParam) == NULL) return NULL;
   1197 
   1198         // set the new stats node to be held by the tag tree
   1199         parent->value.takeOwnership(tmpStatsNode);
   1200 
   1201         // account for the overhead memory
   1202         mm_audit_stats_overhead += sizeof(OsclMemStatsNode) +
   1203                                    oscl_strlen(currentTag.get()) + 1 +
   1204                                    sizeof(MM_Stats_t) +
   1205                                    sizeof(MM_FailInsertParam);
   1206 
   1207         parent = parent->parent;
   1208     }
   1209 
   1210     return statsNode;
   1211 }
   1212 
   1213 
   1214 /* ============================================================================ */
   1215 /*  Function : updateStatsNode()                                                */
   1216 /*  Date     : 10/08/2002                                                       */
   1217 /*  Purpose  : update the node in memory statistics table triggered by an       */
   1218 /*             allocation/de-alocation attempt,                                 */
   1219 /*  In/out   : all parameters are input                                         */
   1220 /*  Return   : true if operation succeeds                                       */
   1221 /*  Modified :                                                                  */
   1222 /* ============================================================================ */
   1223 
   1224 
   1225 bool MM_Audit_Imp::updateStatsNode(OsclMemStatsNode *pCurrStatsNode, const MM_Stats_t& delta, bool add)
   1226 {
   1227     MMAuditCharAutoPtr tag;
   1228     makeValidTag((const char*)(pCurrStatsNode->tag), tag);
   1229 
   1230     //Update
   1231     if (!pCurrStatsNode->pMMStats) return false;
   1232     pCurrStatsNode->pMMStats->update(delta, add);
   1233 
   1234     OsclTagTreeType::iterator miter = mTagTree.find(tag.get());
   1235 
   1236     uint32 depth = miter->depth();
   1237 
   1238     OsclTagTreeType::node_ptr parent = miter->parent;
   1239 
   1240     for (uint32 i = 0; i < depth; i++)
   1241     {
   1242         if (!parent->value->pMMStats) return false;
   1243         parent->value->pMMStats->update(delta, add);
   1244         parent = miter->parent;
   1245     }
   1246 
   1247     return true;
   1248 }
   1249 
   1250 
   1251 /* ============================================================================ */
   1252 /*  Function : updateStatsNodeInFailure()                                       */
   1253 /*  Date     : 11/05/2002                                                       */
   1254 /*  Purpose  : update "pMMStats->numAllocFails" for the current tag node with   */
   1255 /*             its parent tag nodes                                             */
   1256 /*  In/out   : all parameters are input                                         */
   1257 /*  Return   : true if operation succeeds                                       */
   1258 /*  Modified :                                                                  */
   1259 /* ============================================================================ */
   1260 bool MM_Audit_Imp::updateStatsNodeInFailure(const char * tagIn)
   1261 {
   1262     MMAuditCharAutoPtr tag;
   1263     makeValidTag(tagIn, tag);
   1264     OsclTagTreeType::iterator miter = mTagTree.find(tag.get());
   1265     OsclMemStatsNode *pStatsNode;
   1266     if (miter != mTagTree.end())
   1267     {/* found */
   1268         pStatsNode = (miter->value).get();
   1269     }
   1270     else
   1271     {
   1272         pStatsNode = mpStatsNode; // update the root node
   1273     }
   1274 
   1275     return updateStatsNodeInFailure(pStatsNode);
   1276 }
   1277 
   1278 bool MM_Audit_Imp::updateStatsNodeInFailure(OsclMemStatsNode * pStatsNode)
   1279 {
   1280     MMAuditCharAutoPtr tag;
   1281 
   1282     if (!pStatsNode) return false;
   1283 
   1284     makeValidTag((const char*)(pStatsNode->tag), tag);
   1285 
   1286     if (!pStatsNode->pMMStats) return false;
   1287     pStatsNode->pMMStats->numAllocFails++;
   1288 
   1289     OsclTagTreeType::iterator miter = mTagTree.find(tag.get());
   1290 
   1291     uint32 depth = miter->depth();
   1292 
   1293     OsclTagTreeType::node_ptr parent = miter->parent;
   1294 
   1295     for (uint32 i = 0; i < depth; i++)
   1296     {
   1297         if (!parent->value->pMMStats) return false;
   1298         parent->value->pMMStats->numAllocFails++;
   1299         parent = miter->parent;
   1300     }
   1301 
   1302     return true;
   1303 }
   1304 
   1305 /* ============================================================================ */
   1306 /*  Function : isSetFailure()                                                   */
   1307 /*  Date     : 11/05/2002                                                       */
   1308 /*  Purpose  : do allocation failure check                                      */
   1309 /*  In/out   : all parameters are input                                         */
   1310 /*  Return   : true if operation succeeds                                       */
   1311 /*  Modified :                                                                  */
   1312 /* ============================================================================ */
   1313 
   1314 bool MM_Audit_Imp::isSetFailure(const char * tagIn)
   1315 {
   1316     MMAuditCharAutoPtr tag;
   1317     makeValidTag(tagIn, tag);
   1318     OsclTagTreeType::iterator miter = mTagTree.find(tag.get());
   1319     if (miter != mTagTree.end()) /* found */
   1320     {
   1321         OsclMemStatsNode *pStatsNode = (miter->value).get();
   1322         return isSetFailure(pStatsNode);
   1323     }
   1324 
   1325     return false;
   1326 }
   1327 
   1328 bool MM_Audit_Imp::isSetFailure(OsclMemStatsNode* pStatsNode)
   1329 {
   1330     if (pStatsNode == NULL) return false;
   1331 
   1332     if (pStatsNode->pMMFIParam == NULL) return false;
   1333 
   1334     /* decision for deterministic failure insertion */
   1335     if (pStatsNode->pMMFIParam->nAllocNum > 0)
   1336     {
   1337         /* the "+ 1" term in the computation of total_allocs is to
   1338          * count the current allocation
   1339          */
   1340         uint32 total_allocs = pStatsNode->pMMStats->peakNumAllocs + 1 +
   1341                               pStatsNode->pMMStats->numAllocFails ;
   1342 
   1343         if (total_allocs == pStatsNode->pMMFIParam->nAllocNum)
   1344             return true;
   1345     }
   1346 
   1347     return false;
   1348 }
   1349 /* ========================================================================================== */
   1350 /*  Function : retrieveParentTagLength()                                                      */
   1351 /*  Date     : 10/16/2002                                                                     */
   1352 /*  Purpose  : get the length of the parent tag(i.e."a.b.c") of the input tag(i.e. "a.b.c.d") */
   1353 /*             current node and counter it                                                    */
   1354 /*  In/out   : all parameters are input                                                       */
   1355 /*  Return   : length of the parent tag(sub-string) of an input tag                           */
   1356 /*  Modified :                                                                                */
   1357 /* ========================================================================================== */
   1358 
   1359 int32 MM_Audit_Imp::retrieveParentTagLength(const char *tag, int32 bound)
   1360 {
   1361     if (!tag)  return 0;
   1362 
   1363 #define PV_MIN(a,b)   ((a)<(b)? (a):(b))
   1364 
   1365     int count = 0;
   1366     int len = PV_MIN((int32)(oscl_strlen(tag)), bound);
   1367     if (len <= 0)
   1368         return 0;
   1369     else
   1370     {
   1371         bool bFound = false;
   1372         for (count = len - 1; count >= 0; count--)
   1373         {
   1374             if (tag[count] == '.')
   1375             {
   1376                 bFound = true;
   1377                 break;
   1378             }
   1379         }
   1380         if (!bFound)     count = 0;
   1381     }
   1382 
   1383     return count + 1;
   1384 }
   1385 
   1386 void MM_Audit_Imp::retrieveParentTag(char *tag)
   1387 {
   1388     if (!tag)  return;
   1389 
   1390     int32 len = oscl_strlen(tag);
   1391     if (len == 1)
   1392         tag[0] = '\0';
   1393     else
   1394     {
   1395         bool bFound = false;
   1396         for (int32 i = len - 1; i >= 0; i--)
   1397         {
   1398             if (tag[i] == '.')
   1399             {
   1400                 tag[i] = '\0';
   1401                 bFound = true;
   1402                 break;
   1403             }
   1404         }
   1405         if (!bFound)
   1406             tag[0] = '\0';
   1407     }
   1408 }
   1409 
   1410 /* ========================================================================================== */
   1411 /*  Function : makeValidTag()                                                                 */
   1412 /*  Date     : 10/25/2002                                                                     */
   1413 /*  Purpose  : check the input tag and make sure its level would be bounded in maximum tag    */
   1414 /*             level, if its level is larger, then truncate it                                */
   1415 /*             Note that level of "a.b.c.d" = 4                                               */
   1416 /*  In/out   : In: tagIn ; Out: *bFree                                                        */
   1417 /*  Return   : a valid tag within the maximum tag level constraint                            */
   1418 /*  Modified :                                                                                */
   1419 /* ========================================================================================== */
   1420 
   1421 void MM_Audit_Imp::makeValidTag(const char * tagIn, MMAuditCharAutoPtr& autoptr)
   1422 {
   1423 
   1424     if (tagIn == NULL)
   1425     {
   1426         //tagIn = NULL means root tag
   1427         autoptr.setWithoutOwnership(const_cast<char*>(root_tag));
   1428     }
   1429 
   1430     else
   1431     {
   1432         uint32 len = getTagActualSize(tagIn);
   1433         if (len == 0)
   1434         {
   1435             /* len = 0 meaning no need of truncation */
   1436             autoptr.setWithoutOwnership(const_cast<char*>(tagIn));
   1437         }
   1438 
   1439         else
   1440         {
   1441             autoptr.allocate(len + 1);
   1442             oscl_strncpy(autoptr.get(), tagIn, len);
   1443             *(autoptr.get() + len) = '\0';
   1444         }
   1445     }
   1446 }
   1447 
   1448 /* ========================================================================================== */
   1449 /*  Function : getTagActualSize()                                                             */
   1450 /*  Date     : 10/25/2002                                                                     */
   1451 /*  Purpose  : get the actual size of an input tag within the maximum tag level constraint    */
   1452 /*             Note that level of "a.b.c.d" = 4                                               */
   1453 /*  In/out   : In: tagIn ; Out: *bFree                                                        */
   1454 /*  Return   : 0 means no truncation ; >0 means truncated size                                */
   1455 /*  Modified :                                                                                */
   1456 /* ========================================================================================== */
   1457 
   1458 uint32 MM_Audit_Imp::getTagActualSize(const char * tagIn)
   1459 {
   1460     uint32 i, len;
   1461     uint32 level = 0, count = 0;
   1462 
   1463     len = oscl_strlen(tagIn);
   1464     if (len <= 2*mnMaxTagLevel - 1)
   1465         return 0; /* no truncation */
   1466 
   1467     for (i = 0; i < len; i++)
   1468     {
   1469         if (tagIn[i] == '.')
   1470         {
   1471             if (++level == mnMaxTagLevel)
   1472             {
   1473                 count = i;
   1474                 break;
   1475             }
   1476         }
   1477     }
   1478     return count;
   1479 }
   1480 
   1481 
   1482 #endif //if OSCL_BYPASS_MEMMGT
   1483 
   1484 
   1485 
   1486