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