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