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 // -*- c++ -*-
     19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     20 
     21 //                   O S C L _ M E M _ A U D I T
     22 
     23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     24 
     25 /*! \addtogroup osclmemory OSCL Memory
     26  *
     27  * @{
     28  */
     29 
     30 
     31 /*! \file oscl_mem_audit.h
     32     \brief This file contains the definition and partial implementation of MM_Audit class
     33 */
     34 
     35 #ifndef OSCL_MEM_AUDIT_H_INCLUDED
     36 #define OSCL_MEM_AUDIT_H_INCLUDED
     37 
     38 #ifndef OSCL_LOCK_BASE_H_INCLUDED
     39 #include "oscl_lock_base.h"
     40 #endif
     41 
     42 #ifndef OSCL_BASE_ALLOC_H_INCLUDED
     43 #include "oscl_base_alloc.h"
     44 #endif
     45 
     46 #ifndef OSCL_TAGTREE_H_INCLUDED
     47 #include "oscl_tagtree.h"
     48 #endif
     49 
     50 #ifndef OSCL_MEM_H_INCLUDED
     51 #include "oscl_mem.h"
     52 #endif
     53 
     54 #ifndef OSCL_MEM_AUTO_PTR_H_INCLUDED
     55 #include "oscl_mem_auto_ptr.h"
     56 #endif
     57 
     58 #define OSCL_DISABLE_WARNING_TRUNCATE_DEBUG_MESSAGE
     59 #include "osclconfig_compiler_warnings.h"
     60 
     61 
     62 /* DATA TYPES */
     63 struct MM_Stats_t
     64 {
     65     uint32  numBytes;
     66     uint32  peakNumBytes;
     67     uint32  numAllocs;
     68     uint32  peakNumAllocs;
     69     uint32  numAllocFails;
     70     uint32  totalNumAllocs;
     71     uint32  totalNumBytes;
     72 
     73     MM_Stats_t()
     74     {
     75         oscl_memset(this, 0, sizeof(MM_Stats_t));
     76     };
     77     MM_Stats_t(uint32 sizeIn)
     78     {
     79         numBytes = peakNumBytes = sizeIn;
     80         peakNumAllocs = numAllocs = 1;
     81         numAllocFails = 0;
     82         totalNumAllocs = 1;
     83         totalNumBytes = sizeIn;
     84     };
     85 
     86     void reset()
     87     {
     88         oscl_memset(this, 0, sizeof(MM_Stats_t));
     89     };
     90 
     91     void update(const MM_Stats_t& delta, bool add)
     92     {
     93         if (add)
     94         {
     95             numBytes += delta.numBytes;
     96             numAllocs += delta.numAllocs;
     97             numAllocFails += delta.numAllocFails;
     98             if (numBytes > peakNumBytes)
     99             {
    100                 peakNumBytes = numBytes;
    101             }
    102             if (numAllocs > peakNumAllocs)
    103             {
    104                 peakNumAllocs = numAllocs;
    105             }
    106 
    107             totalNumAllocs += delta.numAllocs;
    108             totalNumBytes += delta.numBytes;
    109 
    110         }
    111         else
    112         {
    113             numBytes -= delta.numBytes;
    114             numAllocs -= delta.numAllocs;
    115             numAllocFails -= delta.numAllocFails;
    116         }
    117     }
    118 
    119     void *operator new(oscl_memsize_t size)
    120     {
    121         OSCL_UNUSED_ARG(size);
    122         Oscl_TAlloc<MM_Stats_t, OsclMemBasicAllocator> statsAlloc;
    123         MM_Stats_t *ptr = statsAlloc.allocate(1);
    124         return ptr;
    125     };
    126 
    127     void *operator new(oscl_memsize_t size, MM_Stats_t* ptr)
    128     {
    129         OSCL_UNUSED_ARG(size);
    130         return ptr;
    131     };
    132 
    133 
    134     void operator delete(void *ptr) throw()
    135     {
    136         Oscl_TAlloc<MM_Stats_t, OsclMemBasicAllocator> statsAlloc;
    137         statsAlloc.deallocate((MM_Stats_t*)ptr);
    138     };
    139 
    140     /* won't build on ADS
    141     void operator delete(void *ptr, MM_Stats_t* mptr) {
    142          OSCL_UNUSED_ARG(ptr);
    143          OSCL_UNUSED_ARG(mptr);
    144      };
    145          */
    146 };
    147 
    148 struct MM_FailInsertParam
    149 {
    150     uint32 nAllocNum;
    151     uint16 xsubi[3];
    152     MM_FailInsertParam(): nAllocNum(0)
    153     {
    154         oscl_memset(xsubi, 0, 3*sizeof(xsubi[0]));
    155     }
    156 
    157     void reset()
    158     {
    159         nAllocNum = 0;
    160         oscl_memset(xsubi, 0, 3*sizeof(xsubi[0]));
    161     };
    162 
    163     void *operator new(oscl_memsize_t size)
    164     {
    165         OSCL_UNUSED_ARG(size);
    166         Oscl_TAlloc<MM_FailInsertParam, OsclMemBasicAllocator> failAlloc;
    167         MM_FailInsertParam *ptr = failAlloc.allocate(1);
    168         return ptr;
    169     };
    170 
    171     void *operator new(oscl_memsize_t size, MM_FailInsertParam* ptr)
    172     {
    173         OSCL_UNUSED_ARG(size);
    174         return ptr;
    175     };
    176 
    177 
    178     void operator delete(void *ptr) throw()
    179     {
    180         Oscl_TAlloc<MM_FailInsertParam, OsclMemBasicAllocator> failAlloc;
    181         failAlloc.deallocate((MM_FailInsertParam*)ptr);
    182     };
    183 
    184     /* won't build on ADS
    185     void operator delete(void *ptr, MM_FailInsertParam* mptr) {
    186         OSCL_UNUSED_ARG(ptr);
    187         OSCL_UNUSED_ARG(mptr);
    188     };*/
    189 };
    190 
    191 class OsclMemStatsNode
    192 {
    193     public:
    194 
    195         MM_Stats_t *pMMStats;
    196         MM_FailInsertParam *pMMFIParam;
    197 
    198         /* set a link to map, especially for getting the tags of children nodes */
    199         char *tag;
    200 
    201         OsclMemStatsNode()
    202         {
    203             pMMStats = NULL;
    204             pMMFIParam = NULL;
    205             tag = NULL;
    206         }
    207 
    208         void reset()
    209         {
    210             if (pMMStats) pMMStats->reset();
    211             if (pMMFIParam) pMMFIParam->reset();
    212         };
    213 
    214         ~OsclMemStatsNode()
    215         {
    216             OSCL_DELETE(pMMStats);
    217             OSCL_DELETE(pMMFIParam);
    218             Oscl_TAlloc<char, OsclMemBasicAllocator> charAlloc;
    219             charAlloc.deallocate(tag);
    220         }
    221 
    222         void *operator new(oscl_memsize_t size)
    223         {
    224             OSCL_UNUSED_ARG(size);
    225             Oscl_TAlloc<OsclMemStatsNode, OsclMemBasicAllocator> statsNodeAlloc;
    226             OsclMemStatsNode *ptr = statsNodeAlloc.allocate(1);
    227             return ptr;
    228         };
    229 
    230         void *operator new(oscl_memsize_t size, OsclMemStatsNode* ptr)
    231         {
    232             OSCL_UNUSED_ARG(size);
    233             return ptr;
    234         };
    235 
    236 
    237         void operator delete(void *ptr) throw()
    238         {
    239             Oscl_TAlloc<OsclMemStatsNode, OsclMemBasicAllocator> statsNodeAlloc;
    240             statsNodeAlloc.deallocate((OsclMemStatsNode*)ptr);
    241         };
    242 
    243         /* won't build on ADS
    244         void operator delete(void *ptr, OsclMemStatsNode* mptr) {
    245             OSCL_UNUSED_ARG(ptr);
    246             OSCL_UNUSED_ARG(mptr);
    247         };*/
    248 };
    249 
    250 struct MM_Stats_CB
    251 {
    252     const char *tag;
    253     const MM_Stats_t *pStats;
    254     uint32 num_child_nodes;
    255 
    256     MM_Stats_CB()
    257     {
    258         oscl_memset(this, 0, sizeof(MM_Stats_CB));
    259     }
    260 
    261     void *operator new(oscl_memsize_t size)
    262     {
    263         OSCL_UNUSED_ARG(size);
    264         Oscl_TAlloc<MM_Stats_CB, OsclMemBasicAllocator> statsCBAlloc;
    265         MM_Stats_CB *ptr = statsCBAlloc.allocate(1);
    266         return ptr;
    267     };
    268 
    269     void *operator new(oscl_memsize_t size, MM_Stats_CB* ptr)
    270     {
    271         OSCL_UNUSED_ARG(size);
    272         return ptr;
    273     };
    274 
    275 
    276     void operator delete(void *ptr) throw()
    277     {
    278         Oscl_TAlloc<MM_Stats_CB, OsclMemBasicAllocator> statsCBAlloc;
    279         statsCBAlloc.deallocate((MM_Stats_CB*)ptr);
    280     };
    281 
    282     /* won't build on ADS
    283     void operator delete(void *ptr, MM_Stats_CB* mptr) {
    284         OSCL_UNUSED_ARG(ptr);
    285         OSCL_UNUSED_ARG(mptr);
    286     };*/
    287 };
    288 
    289 #define MM_ALLOC_MAX_QUERY_FILENAME_LEN 128
    290 #define MM_ALLOC_MAX_QUERY_TAG_LEN 64
    291 
    292 struct MM_AllocQueryInfo
    293 {
    294     uint32 allocNum;
    295     char fileName[MM_ALLOC_MAX_QUERY_FILENAME_LEN];
    296     uint32 lineNo;
    297     uint32 size;
    298     const void *pMemBlock;
    299     char tag[MM_ALLOC_MAX_QUERY_TAG_LEN];
    300 };
    301 
    302 
    303 struct MM_AllocInfo
    304 {
    305     uint32 allocNum;
    306     char *pFileName;
    307     uint32 lineNo;
    308     uint32 size;
    309     void *pMemBlock;
    310     OsclMemStatsNode *pStatsNode;
    311     bool bSetFailure;
    312 
    313     MM_AllocInfo()
    314     {
    315         oscl_memset(this, 0, sizeof(MM_AllocInfo));
    316     }
    317 
    318     ~MM_AllocInfo()
    319     {
    320         Oscl_TAlloc<char, OsclMemBasicAllocator> charAlloc;
    321         charAlloc.deallocate(pFileName);
    322     }
    323 
    324 
    325     void *operator new(oscl_memsize_t size)
    326     {
    327         OSCL_UNUSED_ARG(size);
    328         Oscl_TAlloc<MM_AllocInfo, OsclMemBasicAllocator> allocInfoAlloc;
    329         MM_AllocInfo *ptr = allocInfoAlloc.allocate(1);
    330         return ptr;
    331     };
    332 
    333     void *operator new(oscl_memsize_t size, MM_AllocInfo* ptr)
    334     {
    335         OSCL_UNUSED_ARG(size);
    336         return ptr;
    337     };
    338 
    339 
    340     void operator delete(void *ptr) throw()
    341     {
    342         Oscl_TAlloc<MM_AllocInfo, OsclMemBasicAllocator> allocInfoAlloc;
    343         allocInfoAlloc.deallocate((MM_AllocInfo*)ptr);
    344     };
    345 
    346     /* won't build on ADS
    347     void operator delete(void *ptr, MM_AllocInfo* mptr) {
    348         OSCL_UNUSED_ARG(ptr);
    349         OSCL_UNUSED_ARG(mptr);
    350     };*/
    351 };
    352 
    353 
    354 struct MM_AllocNode
    355 {
    356     MM_AllocInfo *pAllocInfo;
    357 
    358     MM_AllocNode *pPrev;
    359     MM_AllocNode *pNext;
    360     MM_AllocNode()
    361     {
    362         oscl_memset(this, 0, sizeof(MM_AllocNode));
    363     }
    364 
    365     ~MM_AllocNode()
    366     {
    367         OSCL_DELETE(pAllocInfo);
    368     }
    369 
    370     void *operator new(oscl_memsize_t size)
    371     {
    372         OSCL_UNUSED_ARG(size);
    373         Oscl_TAlloc<MM_AllocNode, OsclMemBasicAllocator> allocNodeAlloc;
    374         MM_AllocNode *ptr = allocNodeAlloc.allocate(1);
    375         return ptr;
    376     };
    377 
    378     void *operator new(oscl_memsize_t size, MM_AllocNode* ptr)
    379     {
    380         OSCL_UNUSED_ARG(size);
    381         return ptr;
    382     };
    383 
    384 
    385     void operator delete(void *ptr) throw()
    386     {
    387         Oscl_TAlloc<MM_AllocNode, OsclMemBasicAllocator> allocNodeAlloc;
    388         allocNodeAlloc.deallocate((MM_AllocNode*)ptr);
    389     };
    390 
    391     /* won't build on ADS
    392     void operator delete(void *ptr, MM_AllocNode* mptr) {
    393         OSCL_UNUSED_ARG(ptr);
    394         OSCL_UNUSED_ARG(mptr);
    395     };*/
    396 };
    397 
    398 
    399 /* Define internal auto ptr classes that don't go through mem mgmt */
    400 typedef OSCLMemAutoPtr<char, Oscl_TAlloc<char, OsclMemBasicAllocator> > MMAuditCharAutoPtr;
    401 typedef OSCLMemAutoPtr<uint8, Oscl_TAlloc<uint8, _OsclBasicAllocator> > MMAuditUint8AutoPtr;
    402 typedef OSCLMemAutoPtr<MM_AllocNode, Oscl_TAlloc<MM_AllocNode, OsclMemBasicAllocator> > MM_AllocNodeAutoPtr;
    403 
    404 typedef OSCLMemAutoPtr<OsclMemStatsNode, Oscl_TAlloc<OsclMemStatsNode, OsclMemBasicAllocator> > MM_StatsNodeTagTreeType;
    405 typedef OSCLMemAutoPtr<OsclMemStatsNode, Oscl_TAlloc<OsclMemStatsNode, OsclMemBasicAllocator> > OsclMemStatsNodeAutoPtr;
    406 typedef Oscl_TAlloc<MM_StatsNodeTagTreeType, OsclMemBasicAllocator> TagTree_Allocator;
    407 typedef Oscl_TagTree<MM_StatsNodeTagTreeType, TagTree_Allocator> OsclTagTreeType;
    408 
    409 
    410 #define MM_AUDIT_VALIDATE_BLOCK 1
    411 #define MM_AUDIT_PREFILL_FLAG 0x1
    412 #define MM_AUDIT_POSTFILL_FLAG 0x2
    413 #define MM_AUDIT_VALIDATE_ALL_HEAP_FLAG 0x4
    414 #define MM_AUDIT_VALIDATE_ON_FREE_FLAG 0x8
    415 #define MM_AUDIT_ALLOC_NODE_ENABLE_FLAG 0x10
    416 #define MM_AUDIT_SUPPRESS_FILENAME_FLAG 0x20
    417 
    418 #if(PVMEM_INST_LEVEL>0)
    419 #define DEFAULT_MM_AUDIT_MODE (MM_AUDIT_PREFILL_FLAG | \
    420                                MM_AUDIT_POSTFILL_FLAG | \
    421                                MM_AUDIT_VALIDATE_ON_FREE_FLAG | \
    422                                MM_AUDIT_ALLOC_NODE_ENABLE_FLAG )
    423 
    424 
    425 
    426 #else
    427 #define DEFAULT_MM_AUDIT_MODE 0
    428 #endif
    429 
    430 
    431 struct MM_AuditOverheadStats
    432 {
    433     uint32 per_allocation_overhead;
    434     uint32 stats_overhead;
    435 };
    436 
    437 #if OSCL_BYPASS_MEMMGT
    438 //an empty class for compilation only
    439 class MM_Audit_Imp
    440 {
    441     public:
    442 };
    443 #else
    444 class MM_Audit_Imp
    445 {
    446     public:
    447 
    448         /**
    449         *   Constructor, create the root node in statistics table
    450         */
    451         MM_Audit_Imp();
    452 
    453         /**
    454         * A destructor, remove all the nodes in allocation andstatistics table
    455         */
    456         ~MM_Audit_Imp();
    457 
    458         /**
    459         *  The following are APIs
    460         t __nothrow_/
    461         * const __nothrow_
    462         * @returns the memory pointer if operation succeeds.
    463         */
    464         OSCL_IMPORT_REF void *MM_allocate(const OsclMemStatsNode*  statsNode,
    465                                           uint32 sizeIn,
    466                                           const char *pFileName,
    467                                           uint32 lineNumber,
    468                                           bool allocNodeTracking = false);
    469 
    470         /**
    471         *   @returns true if operation succeeds;
    472         */
    473         OSCL_IMPORT_REF bool MM_deallocate(void *pMemBlockIn);
    474 
    475         /**
    476         *   API to get memory statistics through context string(tag)
    477         *   @returns statistics pointer if operation succeeds
    478         */
    479         OSCL_IMPORT_REF MM_Stats_t * MM_GetStats(const char * const  tagIn);
    480 
    481         /**
    482         *   API to get memory statistics in detail through context string(tag) including its subtree
    483         *   @returns statistics pointer array and actual number of nodes if operation succeeds
    484         */
    485         OSCL_IMPORT_REF uint32 MM_GetStatsInDepth(const char *  tagIn, MM_Stats_CB *array_ptr, uint32 max_nodes);
    486 
    487         /**
    488         *   API to get the number of tree nodes including the tag node and its subtree
    489         *   @param tagIn input tag
    490         *   @returns the number of tree nodes ; 0 means no tag node
    491         */
    492         OSCL_IMPORT_REF uint32 MM_GetTreeNodes(const char *  tagIn);
    493 
    494         /**
    495         *   API to add a node and zero out its counters; Note that this tag should be re-used
    496         *   @param tagIn input tag
    497         *   @returns true if operation succeeds;
    498         */
    499         OSCL_IMPORT_REF bool MM_AddTag(const char * tagIn)
    500         {
    501             return (MM_GetTagNode(tagIn) != NULL);
    502         };
    503 
    504         /**
    505         *   API to add a node and zero out its counters;
    506         *    Note that this tag should be re-used
    507         *   @param tagIn input tag
    508         *   @returns pointer to OsclMemStatsNode which should be passed to MM_allocate
    509         */
    510         OSCL_IMPORT_REF const OsclMemStatsNode* MM_GetTagNode(const char * tagIn);
    511 
    512 
    513         /**
    514         *   API to add a node and zero out its counters;
    515         *   Note that this tag should be re-used
    516         *   @param tagIn input tag
    517         *   @returns true if operation succeeds;
    518         */
    519         OSCL_IMPORT_REF const OsclMemStatsNode* MM_GetExistingTag(const char * tagIn);
    520 
    521 
    522         OSCL_IMPORT_REF const OsclMemStatsNode* MM_GetRootNode()
    523         {
    524             return mpStatsNode;
    525         };
    526 
    527         /**
    528         ** These APIs will allocate and release space for alloc node info, to be
    529         ** used with the MM_GetAllocNodeInfo API.
    530         */
    531         OSCL_IMPORT_REF MM_AllocQueryInfo* MM_CreateAllocNodeInfo(uint32 max_array_size);
    532         OSCL_IMPORT_REF void MM_ReleaseAllocNodeInfo(MM_AllocQueryInfo* info);
    533 
    534         /**
    535         *   API to query the list of alloc nodes.  It copies the information
    536         *    into the provided output array.
    537         *   @param output_array the array where the data will be written
    538         *    @param max_array_size the max number of output array elements
    539         *    @param offset the offset into the alloc node list from which the
    540         *     data should begin.
    541         *   @returns the number of valid nodes in the output array
    542         */
    543         OSCL_IMPORT_REF uint32 MM_GetAllocNodeInfo(MM_AllocQueryInfo* output_array,
    544                 uint32 max_array_size, uint32 offset);
    545 
    546         /**
    547         *   API to check the input pointer is a valid pointer to a chunk of memory
    548         *   @param ptrIn input pointer to be validated
    549         *   @returns true if operation succeeds;
    550         */
    551         OSCL_IMPORT_REF bool MM_Validate(const void *ptrIn);
    552 
    553         /**
    554         *   API to get the current allocation number
    555         *   @returns the current allocation number
    556         */
    557         uint32 MM_GetAllocNo(void)
    558         {
    559             return mnAllocNum;
    560         }
    561 
    562         /**
    563         *   API to get the overhead statistics for the
    564         *   memory used by the mm_audit class.
    565         */
    566         void MM_GetOverheadStats(MM_AuditOverheadStats& stats)
    567         {
    568             stats.per_allocation_overhead = mm_audit_per_block_overhead;
    569             stats.stats_overhead = mm_audit_stats_overhead;
    570         }
    571 
    572         /**
    573         *   API to get the number of allocation nodes (records)
    574         *   for allocations that are being tracked individually.
    575         */
    576         uint32 MM_GetNumAllocNodes()
    577         {
    578             return mNumAllocNodes;
    579         };
    580 
    581         /**
    582         *   API to get the operating mode of the mm_audit class.
    583         */
    584         uint32 MM_GetMode(void)
    585         {
    586             return mode;
    587         }
    588 
    589         /**
    590         *   API to get the prefill pattern.  The pattern is used
    591         *    to fill the memory before returning it to the caller.
    592         */
    593         uint8 MM_GetPrefillPattern(void)
    594         {
    595             return prefill_pattern;
    596         }
    597 
    598         /**
    599         *   API to get the postfill pattern.  The pattern is used
    600         *    to fill the memory before freeing it.
    601         */
    602         uint32 MM_GetPostfillPattern(void)
    603         {
    604             return postfill_pattern;
    605         }
    606 
    607         /**
    608         *   API to set the operating mode of the mm_audit class.
    609         */
    610         OSCL_IMPORT_REF void MM_SetMode(uint32 inMode);
    611 
    612         /**
    613         *   API to set the prefill pattern.
    614         */
    615         OSCL_IMPORT_REF void MM_SetPrefillPattern(uint8 pattern);
    616 
    617         /**
    618         *   API to set the postfill pattern.
    619         */
    620         OSCL_IMPORT_REF void MM_SetPostfillPattern(uint8 pattern);
    621 
    622         /**
    623         *   API to set the maximum tag level,i.e. tag level for a.b.c.d = 4
    624         *   @param level input tag level to be set
    625         */
    626         OSCL_IMPORT_REF void MM_SetTagLevel(uint32 level);
    627 
    628         /**
    629         *   API to insert allocation failure deterministically according to allocation number associated with tag
    630         *   @param tagIn input tag
    631         *   @param alloc_number allocation number associated with tag
    632         *   @returns true if operation succeeds;
    633         */
    634         OSCL_IMPORT_REF bool MM_SetFailurePoint(const char * tagIn, uint32 alloc_number);
    635 
    636         /**
    637         *   API to cancel the allocation failure point associated with tag
    638         *   @param tagIn input tag
    639         */
    640         OSCL_IMPORT_REF void MM_UnsetFailurePoint(const char * tagIn);
    641 
    642 
    643         /*
    644         * The following are private member functions
    645         */
    646 
    647 
    648         /**
    649         *    @returns true if operation succeeds;
    650         */
    651         MM_AllocNode* addAllocNode(void *pMem, uint32 sizeIn, OsclMemStatsNode* pStatsNode, const char *pFileName, uint32 lineNumber);
    652         /**
    653         *    @returns true if operation succeeds;
    654         */
    655         OsclMemStatsNode* removeAllocNode(void *pMemBlockIn, uint32& size);
    656         void removeALLAllocNodes();
    657 
    658         /**
    659         *    @returns true if operation succeeds;
    660         */
    661         OsclMemStatsNode* createStatsNode(const char *  tagIn);
    662         /**
    663         *    @returns true if operation succeeds;
    664         */
    665         bool updateStatsNode(OsclMemStatsNode *pCurrStatsNode,
    666                              const MM_Stats_t& pDelta, bool bAdd);
    667         /**
    668         *    @returns true if operation succeeds;
    669         */
    670         bool updateStatsNodeInFailure(const char * tagIn);
    671         bool updateStatsNodeInFailure(OsclMemStatsNode * pStatsNode);
    672         /**
    673         *    @returns true if operation succeeds;
    674         */
    675         bool pruneSubtree(OsclMemStatsNode *pNode);
    676         bool pruneSubtree(const char * tagIn);
    677 
    678         void retrieveParentTag(char *tag);
    679         /**
    680         *    @returns the length of a immediate parent tag for the input tag
    681         */
    682         int32 retrieveParentTagLength(const char *tag, int32 bound);
    683         /**
    684         *    @returns a valid tag; NULL will be converted into root tag
    685         */
    686         void makeValidTag(const char * tagIn, MMAuditCharAutoPtr& autoptr);
    687         /**
    688         *    @returns the size of the truncated tag; 0 means NO truncation
    689         */
    690         uint32 getTagActualSize(const char * tagIn);
    691         /**
    692         *    @returns true if operation succeeds;
    693         */
    694         /**
    695         *    @returns true if operation succeeds;
    696         */
    697         bool isSetFailure(const char * tagIn);
    698 
    699         bool isSetFailure(OsclMemStatsNode * statsNode);
    700         /**
    701         *    @returns true if operation succeeds;
    702         */
    703         static bool validate(void *ptrIn);
    704 
    705         /**
    706         *    @returns audit root pointer.
    707         */
    708         static OsclMemAudit* getAuditRoot(void *ptrIn);
    709 
    710         /**
    711         *  @returns original block size.  leaves if bad pointer.
    712         */
    713         static uint32 getSize(void *ptrIn);
    714 
    715         /**
    716         *    @returns true if operation succeeds;
    717         */
    718         bool validate_all_heap();
    719 
    720     private:
    721 
    722         void populateChildren(const char *tagIn,
    723                               MM_Stats_CB *array_ptr,
    724                               uint32 &curr_array_index,
    725                               uint32 max_nodes);
    726 
    727         /*
    728         * The following are private data members
    729         */
    730 
    731         /**
    732         * mpAllocNode is for the head of the linked list tracking allocated
    733             * nodes.  mpCurrAllocNode is the tail of the list.
    734         */
    735         MM_AllocNode *mpAllocNode, *mpCurrAllocNode;
    736 
    737         /**
    738          * mNumAllocNodes is for the number of allocated nodes on the
    739          * linked list.
    740          */
    741         uint32 mNumAllocNodes;
    742 
    743         /**
    744         * mpStatsNode is for storing memory statistics table
    745         */
    746         OsclMemStatsNode *mpStatsNode;
    747         /**
    748         * a MAP container, mTagTree (key=Tag, value=node addr),
    749         *   is for fast search in memory statistics table given the input Tag
    750         */
    751         OsclTagTreeType          mTagTree;
    752         /**
    753         * tag for the root node in memory statistics table
    754         */
    755         uint32 mnAllocNum;
    756         uint32 mnMaxTagLevel;
    757         uint32 mode;
    758 
    759         uint32 mm_audit_per_block_overhead;
    760         uint32 mm_audit_stats_overhead;
    761 
    762         uint8 prefill_pattern;
    763         uint8 postfill_pattern;
    764 
    765 };
    766 #endif
    767 
    768 #if OSCL_BYPASS_MEMMGT
    769 //an empty class for compilation only.
    770 class OsclMemAudit
    771 {
    772     public:
    773 };
    774 #else
    775 class OsclMemAudit
    776 {
    777     public:
    778         /**
    779         *   Constructor, create the root node in statistics table
    780         */
    781         OsclMemAudit()
    782         {
    783             void * p = _oscl_malloc(sizeof(MM_Audit_Imp));
    784             OsclError::LeaveIfNull(p);
    785 
    786             // this will invoke system placement new operator
    787             _pMM_Audit_Imp = OSCL_PLACEMENT_NEW(p, MM_Audit_Imp());
    788             iLock = &iSingletonLock;
    789             iRefCount = 1;
    790         };
    791 
    792         /**
    793         * A destructor, remove all the nodes in allocation andstatistics table
    794         */
    795         ~OsclMemAudit()
    796         {
    797             _pMM_Audit_Imp->~MM_Audit_Imp();
    798             _oscl_free((void *) _pMM_Audit_Imp);
    799         };
    800 
    801         /**
    802         *  The following are APIs
    803         t __nothrow_/
    804         * const __nothrow_
    805         * @returns the memory pointer if operation succeeds.
    806         */
    807         void *MM_allocate(const OsclMemStatsNode*  statsNode,
    808                           uint32 sizeIn,
    809                           const char *pFileName,
    810                           uint32 lineNumber,
    811                           bool allocNodeTracking = false)
    812         {
    813             // make sure lock is acquired and freed up upon return
    814             iLock->Lock();
    815 
    816             void* result = _pMM_Audit_Imp->MM_allocate(statsNode, sizeIn, pFileName, lineNumber, allocNodeTracking);
    817 
    818             iLock->Unlock();
    819             return result;
    820         };
    821 
    822         /**
    823         *   @returns true if operation succeeds;
    824         */
    825         bool MM_deallocate(void *pMemBlockIn)
    826         {
    827             // make sure lock is acquired and freed up upon return
    828             iLock->Lock();
    829 
    830             bool result = _pMM_Audit_Imp->MM_deallocate(pMemBlockIn);
    831 
    832             iLock->Unlock();
    833             return result;
    834         };
    835 
    836         /**
    837         *   API to get memory statistics through context string(tag)
    838         *   @returns statistics pointer if operation succeeds
    839         */
    840         MM_Stats_t * MM_GetStats(const char * const  tagIn)
    841         {
    842             // make sure lock is acquired and freed up upon return
    843             iLock->Lock();
    844 
    845             MM_Stats_t* result = (_pMM_Audit_Imp->MM_GetStats(tagIn));
    846 
    847             iLock->Unlock();
    848             return result;
    849         };
    850 
    851         /**
    852         *   API to get memory statistics in detail through context string(tag) including its subtree
    853         *   @returns statistics pointer array and actual number of nodes if operation succeeds
    854         */
    855         uint32 MM_GetStatsInDepth(const char *  tagIn, MM_Stats_CB *array_ptr, uint32 max_nodes)
    856         {
    857             // make sure lock is acquired and freed up upon return
    858             iLock->Lock();
    859 
    860             uint32 result = (_pMM_Audit_Imp->MM_GetStatsInDepth(tagIn, array_ptr, max_nodes));
    861 
    862             iLock->Unlock();
    863             return result;
    864         };
    865 
    866         /**
    867         *   API to get the number of tree nodes including the tag node and its subtree
    868         *   @param tagIn input tag
    869         *   @returns the number of tree nodes ; 0 means no tag node
    870         */
    871         uint32 MM_GetTreeNodes(const char *  tagIn)
    872         {
    873             // make sure lock is acquired and freed up upon return
    874             iLock->Lock();
    875 
    876             uint32 result = (_pMM_Audit_Imp->MM_GetTreeNodes(tagIn));
    877 
    878             iLock->Unlock();
    879             return result;
    880         };
    881 
    882         /**
    883         *   API to add a node and zero out its counters; Note that this tag should be re-used
    884         *   @param tagIn input tag
    885         *   @returns true if operation succeeds;
    886         */
    887         bool MM_AddTag(const char * tagIn)
    888         {
    889             return (MM_GetTagNode(tagIn) != NULL);
    890         };
    891 
    892         /**
    893         *   API to add a node and zero out its counters;
    894         *    Note that this tag should be re-used
    895         *   @param tagIn input tag
    896         *   @returns pointer to OsclMemStatsNode which should be passed to MM_allocate
    897         */
    898         const OsclMemStatsNode* MM_GetTagNode(const char * tagIn)
    899         {
    900             // make sure lock is acquired and freed up upon return
    901             iLock->Lock();
    902 
    903             const OsclMemStatsNode* result = (_pMM_Audit_Imp->MM_GetTagNode(tagIn));
    904 
    905             iLock->Unlock();
    906             return result;
    907         };
    908 
    909 
    910         /**
    911         *   API to add a node and zero out its counters;
    912         *   Note that this tag should be re-used
    913         *   @param tagIn input tag
    914         *   @returns true if operation succeeds;
    915         */
    916         const OsclMemStatsNode* MM_GetExistingTag(const char * tagIn)
    917         {
    918             // make sure lock is acquired and freed up upon return
    919             iLock->Lock();
    920 
    921             const OsclMemStatsNode* result = (_pMM_Audit_Imp->MM_GetExistingTag(tagIn));
    922 
    923             iLock->Unlock();
    924             return result;
    925         };
    926 
    927 
    928         const OsclMemStatsNode* MM_GetRootNode()
    929         {
    930             return (_pMM_Audit_Imp->MM_GetRootNode());
    931         };
    932 
    933         /**
    934         *   API to query the list of alloc nodes.  It copies the information
    935         *    into the provided output array.
    936         *   @param output_array the array where the data will be written
    937         *    @param max_array_size the max number of output array elements
    938         *    @param offset the offset into the alloc node list from which the
    939         *     data should begin.
    940         *   @returns the number of valid nodes in the output array
    941         */
    942         uint32 MM_GetAllocNodeInfo(MM_AllocQueryInfo* output_array,
    943                                    uint32 max_array_size, uint32 offset)
    944         {
    945             // make sure lock is acquired and freed up upon return
    946             iLock->Lock();
    947 
    948             uint32 result = (_pMM_Audit_Imp->MM_GetAllocNodeInfo(output_array, max_array_size, offset));
    949 
    950             iLock->Unlock();
    951             return result;
    952         };
    953 
    954         MM_AllocQueryInfo* MM_CreateAllocNodeInfo(uint32 max_array_size)
    955         {
    956             return _pMM_Audit_Imp->MM_CreateAllocNodeInfo(max_array_size);
    957         }
    958         void MM_ReleaseAllocNodeInfo(MM_AllocQueryInfo* info)
    959         {
    960             _pMM_Audit_Imp->MM_ReleaseAllocNodeInfo(info);
    961         }
    962 
    963         /**
    964         *   API to check the input pointer is a valid pointer to a chunk of memory
    965         *   @param ptrIn input pointer to be validated
    966         *   @returns true if operation succeeds;
    967         */
    968         bool MM_Validate(const void *ptrIn)
    969         {
    970             // make sure lock is acquired and freed up upon return
    971             iLock->Lock();
    972 
    973             bool result = (_pMM_Audit_Imp->MM_Validate(ptrIn));
    974 
    975             iLock->Unlock();
    976             return result;
    977         };
    978 
    979         /**
    980         *   API to get the current allocation number
    981         *   @returns the current allocation number
    982         */
    983         uint32 MM_GetAllocNo(void)
    984         {
    985             return (_pMM_Audit_Imp->MM_GetAllocNo());
    986         };
    987 
    988         /**
    989         *   API to get the overhead statistics for the
    990         *   memory used by the mm_audit class.
    991         */
    992         void MM_GetOverheadStats(MM_AuditOverheadStats& stats)
    993         {
    994             _pMM_Audit_Imp->MM_GetOverheadStats(stats);
    995         };
    996 
    997         /**
    998         *   API to get the number of allocation nodes (records)
    999         *   for allocations that are being tracked individually.
   1000         */
   1001         uint32 MM_GetNumAllocNodes()
   1002         {
   1003             return (_pMM_Audit_Imp->MM_GetNumAllocNodes());
   1004         };
   1005 
   1006         /**
   1007         *   API to get the operating mode of the mm_audit class.
   1008         */
   1009         uint32 MM_GetMode(void)
   1010         {
   1011             return (_pMM_Audit_Imp->MM_GetMode());
   1012         };
   1013 
   1014         /**
   1015         *   API to get the prefill pattern.  The pattern is used
   1016         *    to fill the memory before returning it to the caller.
   1017         */
   1018         uint8 MM_GetPrefillPattern(void)
   1019         {
   1020             return (_pMM_Audit_Imp->MM_GetPrefillPattern());
   1021         };
   1022 
   1023         /**
   1024         *   API to get the postfill pattern.  The pattern is used
   1025         *    to fill the memory before freeing it.
   1026         */
   1027         uint32 MM_GetPostfillPattern(void)
   1028         {
   1029             return (_pMM_Audit_Imp->MM_GetPostfillPattern());
   1030         };
   1031 
   1032         /**
   1033         *   API to set the operating mode of the mm_audit class.
   1034         */
   1035         void MM_SetMode(uint32 inMode)
   1036         {
   1037             // make sure lock is acquired and freed up upon return
   1038             iLock->Lock();
   1039 
   1040             _pMM_Audit_Imp->MM_SetMode(inMode);
   1041 
   1042             iLock->Unlock();
   1043         };
   1044 
   1045         /**
   1046         *   API to set the prefill pattern.
   1047         */
   1048         void MM_SetPrefillPattern(uint8 pattern)
   1049         {
   1050             // make sure lock is acquired and freed up upon return
   1051             iLock->Lock();
   1052 
   1053             _pMM_Audit_Imp->MM_SetPrefillPattern(pattern);
   1054 
   1055             iLock->Unlock();
   1056         };
   1057 
   1058         /**
   1059         *   API to set the postfill pattern.
   1060         */
   1061         void MM_SetPostfillPattern(uint8 pattern)
   1062         {
   1063             // make sure lock is acquired and freed up upon return
   1064             iLock->Lock();
   1065 
   1066             _pMM_Audit_Imp->MM_SetPostfillPattern(pattern);
   1067 
   1068             iLock->Unlock();
   1069         };
   1070 
   1071         /**
   1072         *   API to set the maximum tag level,i.e. tag level for a.b.c.d = 4
   1073         *   @param level input tag level to be set
   1074         */
   1075         void MM_SetTagLevel(uint32 level)
   1076         {
   1077             // make sure lock is acquired and freed up upon return
   1078             iLock->Lock();
   1079 
   1080             _pMM_Audit_Imp->MM_SetTagLevel(level);
   1081 
   1082             iLock->Unlock();
   1083         };
   1084 
   1085         /**
   1086         *   API to insert allocation failure deterministically according to allocation number associated with tag
   1087         *   @param tagIn input tag
   1088         *   @param alloc_number allocation number associated with tag
   1089         *   @returns true if operation succeeds;
   1090         */
   1091         bool MM_SetFailurePoint(const char * tagIn, uint32 alloc_number)
   1092         {
   1093             // make sure lock is acquired and freed up upon return
   1094             iLock->Lock();
   1095 
   1096             bool result = (_pMM_Audit_Imp->MM_SetFailurePoint(tagIn, alloc_number));
   1097 
   1098             iLock->Unlock();
   1099             return result;
   1100         };
   1101 
   1102 
   1103         /**
   1104         *   API to cancel the allocation failure point associated with tag
   1105         *   @param tagIn input tag
   1106         */
   1107         void MM_UnsetFailurePoint(const char * tagIn)
   1108         {
   1109             // make sure lock is acquired and freed up upon return
   1110             iLock->Lock();
   1111 
   1112             _pMM_Audit_Imp->MM_UnsetFailurePoint(tagIn);
   1113 
   1114             iLock->Unlock();
   1115         };
   1116 
   1117         int32 MM_GetRefCount()
   1118         {
   1119             int32 count;
   1120             iLock->Lock();
   1121             count = iRefCount;
   1122             iLock->Unlock();
   1123             return count;
   1124         }
   1125 
   1126         /**
   1127         *   API to obtain mem lock ptr
   1128         *
   1129         */
   1130 
   1131         OsclLockBase* GetLock()
   1132         {
   1133             return iLock;
   1134         };
   1135 
   1136         /*
   1137         * The following are private member functions
   1138         */
   1139 
   1140     private:
   1141         /**
   1142         *    @returns true if operation succeeds;
   1143         */
   1144         MM_AllocNode* addAllocNode(void *pMem, uint32 sizeIn, OsclMemStatsNode* pStatsNode,
   1145                                    const char *pFileName, uint32 lineNumber)
   1146         {
   1147             return (_pMM_Audit_Imp->addAllocNode(pMem, sizeIn, pStatsNode, pFileName, lineNumber));
   1148         }
   1149 
   1150         /**
   1151         *    @returns true if operation succeeds;
   1152         */
   1153         OsclMemStatsNode* removeAllocNode(void *pMemBlockIn, uint32& size)
   1154         {
   1155             return (_pMM_Audit_Imp->removeAllocNode(pMemBlockIn, size));
   1156         }
   1157 
   1158         void removeALLAllocNodes()
   1159         {
   1160             _pMM_Audit_Imp->removeALLAllocNodes();
   1161         }
   1162 
   1163         /**
   1164         *    @returns true if operation succeeds;
   1165         */
   1166         OsclMemStatsNode* createStatsNode(const char *  tagIn)
   1167         {
   1168             return (_pMM_Audit_Imp->createStatsNode(tagIn));
   1169         }
   1170 
   1171         /**
   1172         *    @returns true if operation succeeds;
   1173         */
   1174         bool updateStatsNode(OsclMemStatsNode *pCurrStatsNode,
   1175                              const MM_Stats_t& pDelta, bool bAdd)
   1176         {
   1177             return (_pMM_Audit_Imp->updateStatsNode(pCurrStatsNode, pDelta, bAdd));
   1178         }
   1179 
   1180         /**
   1181         *    @returns true if operation succeeds;
   1182         */
   1183         bool updateStatsNodeInFailure(const char * tagIn)
   1184         {
   1185             return (_pMM_Audit_Imp->updateStatsNodeInFailure(tagIn));
   1186         }
   1187 
   1188         bool updateStatsNodeInFailure(OsclMemStatsNode * pStatsNode)
   1189         {
   1190             return (_pMM_Audit_Imp->updateStatsNodeInFailure(pStatsNode));
   1191         }
   1192 
   1193         /**
   1194         *    @returns true if operation succeeds;
   1195         */
   1196         bool pruneSubtree(OsclMemStatsNode *pNode)
   1197         {
   1198             return (_pMM_Audit_Imp->pruneSubtree(pNode));
   1199         }
   1200 
   1201         bool pruneSubtree(const char * tagIn)
   1202         {
   1203             return (_pMM_Audit_Imp->pruneSubtree(tagIn));
   1204         }
   1205 
   1206         void retrieveParentTag(char *tag)
   1207         {
   1208             (_pMM_Audit_Imp->retrieveParentTag(tag));
   1209         }
   1210 
   1211         /**
   1212         *    @returns the length of a immediate parent tag for the input tag
   1213         */
   1214         int32 retrieveParentTagLength(const char *tag, int32 bound)
   1215         {
   1216             return (_pMM_Audit_Imp->retrieveParentTagLength(tag, bound));
   1217         }
   1218 
   1219         /**
   1220         *    @returns a valid tag; NULL will be converted into root tag
   1221         */
   1222         void makeValidTag(const char * tagIn, MMAuditCharAutoPtr& autoptr)
   1223         {
   1224             (_pMM_Audit_Imp->makeValidTag(tagIn, autoptr));
   1225         }
   1226 
   1227         /**
   1228         *    @returns the size of the truncated tag; 0 means NO truncation
   1229         */
   1230         uint32 getTagActualSize(const char * tagIn)
   1231         {
   1232             return (_pMM_Audit_Imp->getTagActualSize(tagIn));
   1233         }
   1234 
   1235         /**
   1236         *    @returns true if operation succeeds;
   1237         */
   1238         bool isSetFailure(const char * tagIn)
   1239         {
   1240             return (_pMM_Audit_Imp->isSetFailure(tagIn));
   1241         }
   1242 
   1243         bool isSetFailure(OsclMemStatsNode * statsNode)
   1244         {
   1245             return (_pMM_Audit_Imp->isSetFailure(statsNode));
   1246         }
   1247 
   1248         /**
   1249         *    @returns true if operation succeeds;
   1250         */
   1251         bool validate(void *ptrIn)
   1252         {
   1253             return (_pMM_Audit_Imp->validate(ptrIn));
   1254         }
   1255 
   1256         /**
   1257         *    @returns true if operation succeeds;
   1258         */
   1259         bool validate_all_heap()
   1260         {
   1261             return (_pMM_Audit_Imp->validate_all_heap());
   1262         }
   1263 
   1264 
   1265     private:
   1266 
   1267         /*
   1268         * The following are private data members
   1269         */
   1270 
   1271         MM_Audit_Imp *_pMM_Audit_Imp;
   1272         OsclLockBase *iLock;
   1273 
   1274         /**
   1275         *  Use OSCL singleton version
   1276         */
   1277         _OsclBasicLock iSingletonLock;
   1278         int32 iRefCount;
   1279         friend class OsclMemGlobalAuditObject;
   1280 
   1281 };
   1282 #endif
   1283 
   1284 #endif //OSCL_MEM_AUDIT_H_INCLUDED
   1285 
   1286 /*! @} */
   1287