gwnavruntime/kernel/HeapPT/HeapPT_DebugInfo.h Source File

HeapPT_DebugInfo.h
Go to the documentation of this file.
1 /*
2 * Copyright 2015 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 /**************************************************************************
8 
9 Filename : HeapPT_DebugInfo.h
10 Content : Debug and statistics implementation.
11 Created : July 14, 2008
12 Authors : Maxim Shemanarev
13 
14 **************************************************************************/
15 
16 #ifndef INC_KY_Kernel_HeapPT_DebugInfo_H
17 #define INC_KY_Kernel_HeapPT_DebugInfo_H
18 
20 
21 #ifdef KY_MEMORY_ENABLE_DEBUG_INFO
22 
28 
29 namespace Kaim { namespace HeapPT {
30 
31 class AllocEngine;
32 
33 using namespace Heap;
34 
35 //------------------------------------------------------------------------
36 template<class T>
37 struct DebugDataPool : ListNode<DebugDataPool<T> >
38 {
39  typedef DebugDataPool<T> SelfType;
40 
41  DebugDataPool() : UseCount(0) {}
42 
43  static UPInt GetSize(UPInt bytes)
44  {
45  return (bytes - sizeof(SelfType)) / sizeof(T);
46  }
47 
48  T* GetElement(UPInt i)
49  {
50  return (T*)((UByte*)this + sizeof(SelfType) + i*sizeof(T));
51  }
52  UPInt UseCount;
53 };
54 
55 
56 //------------------------------------------------------------------------
57 struct DebugNode : ListNode<DebugNode>
58 {
59  enum
60  {
61  // Initially DebugData is created, as a single linked list
62  // of nodes. After exceeding PageUpperLimit it is converted into
63  // DebugPage. When DataCount gets less then PageLowerLimit
64  // the DebugPage is converted back to DebugData.
65  // It works like a classical Schmitt trigger with a hysteresis
66  // loop:
67  // LowerLimit
68  // /-------<-------+-----Page----
69  // | |
70  // | Hysteresis |
71  // | Loop |
72  // | |
73  // ----Chain----+------->-------/
74  // UpperLimit
75  //----------------------------------------------------------------
76  PageUpperLimit = 12,
77  PageLowerLimit = 6,
78  NodePageFlag = 0x8000U,
79  NodePageMask = 0x7FFFU,
80  ChainLimit = 10
81  };
82 
83  UPInt IsPage() const
84  {
85  return DataCount & UPInt(NodePageFlag);
86  }
87 
88  UPInt GetDataCount() const
89  {
90  return DataCount & UPInt(NodePageMask);
91  }
92 
93  UPInt Increment()
94  {
95  return (++DataCount) & UPInt(NodePageMask);
96  }
97 
98  UPInt Decrement()
99  {
100  return (--DataCount) & UPInt(NodePageMask);
101  }
102 
103  UPIntHalf DataCount;
104  UPIntHalf ChainCount;
105 };
106 
107 
108 //------------------------------------------------------------------------
109 struct DebugData : DebugNode
110 {
111  typedef DebugDataPool<DebugData> DataPool;
112 
113  void Clear()
114  {
115  DataCount = 0;
116  ChainCount = 0;
117  pParent = 0;
118  pNextData = 0;
119  RefCount = 0;
120  Address = 0;
121  Size = 0;
122  memset(&Info, 0, sizeof(Info));
123  }
124 
125  void MessUp()
126  {
127  memset(&DataCount, 0xFE, sizeof(DataCount));
128  memset(&ChainCount, 0xFE, sizeof(ChainCount));
129  memset(&pParent, 0xFE, sizeof(pParent));
130  memset(&pNextData, 0xFE, sizeof(pNextData));
131  memset(&RefCount, 0xFE, sizeof(RefCount));
132  memset(&Address, 0xFE, sizeof(Address));
133  memset(&Size, 0xFE, sizeof(Size));
134  memset(&Info, 0xFE, sizeof(Info));
135  }
136 
137 
138  DataPool* pDataPool;
139  DebugData* pParent;
140  DebugData* pNextData; // Next data entry in chain
141  UPInt RefCount;
142  UPInt Address;
143  UPInt Size;
144  AllocInfo Info;
145 };
146 
147 
148 
149 //------------------------------------------------------------------------
150 struct DebugPage : DebugNode
151 {
152  typedef DebugDataPool<DebugPage> DataPool;
153 
154  enum
155  {
156  PageShift = 5,
157  PageSize = 1 << PageShift, // Must not exceed the number of bits in UPInt
158 
159  AddrShift = Heap_PageShift - PageShift,
160  AddrSize = 1 << AddrShift,
161  AddrMask = AddrSize-1
162  };
163 
164  void Clear()
165  {
166  DataCount = UPInt(NodePageFlag);
167  ChainCount = 0;
168  Mask = 0;
169  memset(pData, 0, sizeof(pData));
170  }
171 
172  void MessUp()
173  {
174  memset(&DataCount, 0xFE, sizeof(DataCount));
175  memset(&ChainCount, 0xFE, sizeof(ChainCount));
176  memset(&Mask, 0xFE, sizeof(Mask));
177  memset(pData, 0xFE, sizeof(pData));
178  }
179 
180  DataPool* pDataPool;
181  UPInt Mask;
182  DebugData* pData[PageSize];
183 };
184 
185 
186 
187 
188 //------------------------------------------------------------------------
189 class DebugStorage
190 {
191  enum
192  {
193  PoolSize = Heap_DebugAllocPoolSize,
194  AddrShift = DebugPage::AddrShift,
195  AddrSize = DebugPage::AddrSize,
196  AddrMask = DebugPage::AddrMask,
197  PageUpperLimit = DebugNode::PageUpperLimit,
198  PageLowerLimit = DebugNode::PageLowerLimit,
199  };
200 
201  typedef DebugDataPool<DebugData> DataPoolType;
202  typedef DebugDataPool<DebugPage> PagePoolType;
203 
204 public:
205  struct DebugDataPtr
206  {
207  DebugDataPtr() : pNode(0), Index(~UPInt(0)), pSelf(0), pPrev(0) {}
208  DebugNode* pNode;
209  UPInt Index;
210  DebugData* pSelf;
211  DebugData* pPrev;
212  };
213 
214  DebugStorage(Granulator* alloc, LockSafe* rootLocker);
215 
216  unsigned GetStatId(UPInt parentAddr, const AllocInfo* info);
217 
218  bool AddAlloc(UPInt parentAddr, bool autoHeap, UPInt thisAddr,
219  UPInt size, UPInt usable, const AllocInfo* info);
220 
221  void RemoveAlloc(UPInt addr, UPInt usable);
222 
223  void RelinkAlloc(DebugDataPtr* ptr, UPInt oldAddr,
224  UPInt newAddr, UPInt newSize, UPInt usable);
225 
226  void CheckDataTail(const DebugDataPtr* ptr, UPInt usable);
227 
228  void FreeAll();
229 
230  void GetDebugData(UPInt addr, DebugDataPtr* ptr);
231 
232  void UnlinkAlloc(UPInt addr, DebugDataPtr* ptr);
233 
234  void GetStats(AllocEngine* allocator, StatBag* bag) const;
235 
236  const DebugData* GetFirstEntry() const;
237  const DebugData* GetNextEntry(const DebugData* entry) const;
238 
239  void VisitMem(MemVisitor* visitor, unsigned flags) const;
240 
241  bool DumpMemoryLeaks(const char* heapName);
242 
243  void UltimateCheck();
244 
245  UPInt GetUsedSpace() const;
246 
247 private:
248  bool allocDataPool();
249  void freeDataPool(DataPoolType* pool);
250  bool allocPagePool();
251  void freePagePool(PagePoolType* pool);
252 
253  DebugPage* allocDebugPage();
254  void freeDebugPage(DebugPage* page);
255 
256  DebugData* allocDebugData();
257  void freeDebugData(DebugData* data);
258  void unlinkDebugData(DebugDataPtr* ptr);
259  void linkDebugData(DebugData* data);
260  void findInChainWithin(DebugData* chain, UPInt addr, DebugDataPtr* ptr);
261  void findInChainExact(DebugData* chain, UPInt addr, DebugDataPtr* ptr);
262  void findInNodeWithin(DebugNode* node, UPInt idx, UPInt addr, DebugDataPtr* ptr);
263  void findDebugData(UPInt addr, bool autoHeap, DebugDataPtr* ret);
264  void linkToPage(DebugPage* page, DebugData* data);
265  void convertToChain(DebugPage* page, DebugData* oldData);
266  bool convertToPage(DebugData* chain, DebugData* newData);
267  void fillDataTail(DebugData* data, UPInt usable);
268  void reportViolation(DebugData* data, const char* msg);
269 
270  template<class T, class B>
271  void visitMem(const List<T,B>& lst, UPInt dataSize,
272  MemVisitor* visitor,
273  MemVisitor::Category cat,
274  HeapSegment* seg) const
275  {
276  const T* ptr = lst.GetFirst();
277  while(!lst.IsNull(ptr))
278  {
279  const TreeSeg* allocSeg = pAllocator->GetAllocSegment(ptr);
280  seg->pData = allocSeg->Buffer;
281  seg->DataSize = allocSeg->Size;
282  visitor->Visit(seg, UPInt(ptr), dataSize, cat);
283  ptr = (const T*)(ptr->pNext);
284  }
285  }
286 
287  Granulator* pAllocator;
288  List<DataPoolType> DataPools;
289  List<PagePoolType> PagePools;
290  List<DebugData, DebugNode> UsedDataList;
291  List<DebugData, DebugNode> FreeDataList;
292  List<DebugPage, DebugNode> FreePageList;
293  LockSafe* pRootLocker;
294 };
295 
296 }} // Kaim::Heap
297 
298 #endif // KY_MEMORY_ENABLE_DEBUG_INFO
299 
300 #endif
301 
Definition: gamekitcrowddispersion.h:20