• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
MM_Audit_Imp()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 
~MM_Audit_Imp()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 
MM_allocate(const OsclMemStatsNode * pInStatsNode,uint32 sizeIn,const char * pFileName,uint32 lineNumber,bool allocNodeTracking)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 
MM_deallocate(void * pMemBlockIn)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 
MM_GetTreeNodes(const char * tagIn)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 
MM_GetStats(const char * const tagIn)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 
MM_GetStatsInDepth(const char * tagIn,MM_Stats_CB * array_ptr,uint32 max_nodes)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 
populateChildren(const char * tagIn,MM_Stats_CB * array_ptr,uint32 & curr_array_index,uint32 max_nodes)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 
MM_GetTagNode(const char * tagIn)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 
MM_GetExistingTag(const char * tagIn)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 
MM_Validate(const void * ptrIn)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 
MM_SetTagLevel(uint32 level)555 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetTagLevel(uint32 level)
556 {
557     if (level >= 1) mnMaxTagLevel = level;
558 }
559 
560 
MM_SetMode(uint32 in_mode)561 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetMode(uint32 in_mode)
562 {
563     mode = in_mode;
564 }
565 
566 
MM_SetPrefillPattern(uint8 pattern)567 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetPrefillPattern(uint8 pattern)
568 {
569     prefill_pattern = pattern;
570 }
571 
572 
MM_SetPostfillPattern(uint8 pattern)573 OSCL_EXPORT_REF void MM_Audit_Imp::MM_SetPostfillPattern(uint8 pattern)
574 {
575     postfill_pattern = pattern;
576 }
577 
MM_CreateAllocNodeInfo(uint32 array_size)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 
MM_ReleaseAllocNodeInfo(MM_AllocQueryInfo * output_array)583 OSCL_EXPORT_REF void MM_Audit_Imp::MM_ReleaseAllocNodeInfo(MM_AllocQueryInfo* output_array)
584 {
585     _oscl_free(output_array);
586 }
587 
MM_GetAllocNodeInfo(MM_AllocQueryInfo * output_array,uint32 max_array_size,uint32 offset)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 
MM_SetFailurePoint(const char * tagIn,uint32 alloc_number)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 
MM_UnsetFailurePoint(const char * tagIn)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 
addAllocNode(void * pMemBlockIn,uint32 sizeIn,OsclMemStatsNode * pStatsNode,const char * pFileName,uint32 lineNumber)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 
removeAllocNode(void * pMemBlockIn,uint32 & size)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 
removeALLAllocNodes()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 
validate_all_heap()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 
validate(void * ptrIn)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*/
getAuditRoot(void * ptrIn)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 
getSize(void * ptrIn)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 
createStatsNode(const char * tagIn)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 
updateStatsNode(OsclMemStatsNode * pCurrStatsNode,const MM_Stats_t & delta,bool add)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 /* ============================================================================ */
updateStatsNodeInFailure(const char * tagIn)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 
updateStatsNodeInFailure(OsclMemStatsNode * pStatsNode)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 
isSetFailure(const char * tagIn)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 
isSetFailure(OsclMemStatsNode * pStatsNode)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 
retrieveParentTagLength(const char * tag,int32 bound)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 
retrieveParentTag(char * tag)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 
makeValidTag(const char * tagIn,MMAuditCharAutoPtr & autoptr)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 
getTagActualSize(const char * tagIn)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