• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 // -*- 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