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