1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
36 package ti.sysbios.heaps;
37
38 import xdc.runtime.Memory;
39 import xdc.runtime.IHeap;
40 import ti.sysbios.knl.Task;
41 import ti.sysbios.knl.Queue;
42 import xdc.rov.ViewInfo;
43
44 /*!
45 * ======== HeapTrack ========
46 * Heap manager that enables tracking of all allocated blocks.
47 *
48 * HeapTrack manager provides functions to allocate and free storage from a
49 * configured heap which inherits from IHeap. The calling context is going to
50 * match the heap being used.
51 *
52 * HeapTrack is useful for detecting memory leaks, double frees and buffer
53 * overflows. There is a performance overhead cost when using heap track as
54 * well as a size impact. Every alloc will include a {@link #Tracker}
55 * structure (plus memory to get proper alignment of the stucture) at
56 * the end of the buffer that should not be modified by the user. It is
57 * important to remember this when deciding on heap sizes and you may have to
58 * adjust the total size or buffer sizes (for HeapBuf/HeapMultiBuf).
59 *
60 * ROV displays peaks and current in-use for both allocated memory (requested
61 * size + Tracker structure) and requested memory (without Tracker).
62 *
63 * The information stored in the tracker packet is used to display information
64 * in RTOS Object Viewer (ROV) as well as with the printTask and printHeap
65 * functions.
66 *
67 * The asserts used in this module are listed below and include error checking
68 * for double frees, calling printHeap with a null handle, buffer overflows
69 * and deleting a non empty heap.
70 */
71
72 @InstanceFinalize
73
74 module HeapTrack inherits xdc.runtime.IHeap {
75
76 /*!
77 * ======== BasicView ========
78 * @_nodoc
79 */
80 metaonly struct BasicView {
81 IHeap.Handle heapHandle;
82 String inUse;
83 String inUsePeak;
84 String inUseWithoutTracker;
85 String inUsePeakWithoutTracker;
86 }
87
88 /*!
89 * ======== TaskView ========
90 * @_nodoc
91 */
92 metaonly struct TaskView {
93 String block;
94 String heapHandle;
95 String blockAddr;
96 String requestedSize;
97 String clockTick;
98 String overflow;
99 }
100
101 /*!
102 * ======== HeapListView ========
103 * @_nodoc
104 */
105 metaonly struct HeapListView {
106 String block;
107 String taskHandle;
108 String heapHandle;
109 String blockAddr;
110 String requestedSize;
111 String clockTick;
112 String overflow;
113 }
114
115 /*! @_nodoc */
116 @Facet
117 metaonly config ViewInfo.Instance rovViewInfo =
118 ViewInfo.create({
119 viewMap: [
120 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn:
121 'viewInitBasic', structName: 'BasicView'}],
122 ['HeapAllocList', {type: ViewInfo.INSTANCE_DATA, viewInitFxn:
123 'viewInitHeapList', structName: 'HeapListView'}],
124 ['TaskAllocList', {type: ViewInfo.TREE_TABLE, viewInitFxn:
125 'viewInitTask', structName: 'TaskView'}],
126 ]
127 });
128
129 /*!
130 * ======== Tracker ========
131 * Structure added to the end of each allocated block
132 *
133 * When a block is allocated from a HeapTrack heap with a size,
134 * internally HeapTrack calls Memory_alloc on the configured
135 * {@link #heap}. The value of sizeof(HeapTrack_Tracker)
136 * is added to the requested size.
137 *
138 * For example, if the caller makes the following call (where heapHandle
139 * is an HeapTrack handle that has been converted to an IHeap_Handle).
140 * @p(code)
141 * buf = Memory_alloc(heapHandle, MYSIZE, MYALIGN, &eb);
142 * @p
143 *
144 * Internally, HeapTrack will make the following call
145 * (where size is MYSIZE, align is MYALIGN and obj is the HeapTrack handle).
146 * @p(code)
147 * block = Memory_alloc(obj->heap, size + sizeof(HeapTrack_Tracker), align, &eb);
148 * @p
149 *
150 * When using HeapTrack, depending on the actual heap
151 * (i.e. {@link #heap}), you might need to make adjustments to the heap
152 * (e.g. increase the blockSize if using a HeapBuf instance).
153 *
154 * The HeapTrack module manages the contents of this structure and should
155 * not be directly accessing them.
156 */
157 struct Tracker {
158 UArg scribble;
159 Queue.Elem queElem;
160 SizeT size;
161 UInt32 tick;
162 Task.Handle taskHandle;
163 }
164
165 /*!
166 * ======== STARTSCRIBBLE ========
167 * @_nodoc
168 * Constant used to help detect over-writing of a buffer
169 */
170 const UArg STARTSCRIBBLE = 0xa5a5a5a5;
171
172 /*!
173 * ======== printTask ========
174 * Print out the blocks that are currently allocated by a task
175 *
176 * Iterates through all instances of HeapTrack and prints out information
177 * about all allocated blocks of memory for a given task handle. This
178 * function is not thread safe.
179 *
180 * @params(taskHandle) Task to print stats for
181 */
182 Void printTask(Task.Handle taskHandle);
183
184 /*!
185 * ======== A_doubleFree ========
186 * Assert raised when freeing a buffer that was already freed
187 */
188 config xdc.runtime.Assert.Id A_doubleFree =
189 {msg: "A_doubleFree: Buffer already free"};
190
191 /*!
192 * ======== A_bufOverflow ========
193 * Assert raised when freeing memory with corrupted data or using the
194 * wrong size
195 */
196 config xdc.runtime.Assert.Id A_bufOverflow =
197 {msg: "A_bufOverflow: Buffer overflow"};
198
199 /*!
200 * ======== A_notEmpty ========
201 * Assert raised when deleting a non-empty heap
202 */
203 config xdc.runtime.Assert.Id A_notEmpty =
204 {msg: "A_notEmpty: Heap not empty"};
205
206
207 /*!
208 * ======== A_nullObject ========
209 * Assert raised when calling printTask with a null HeapTrack object
210 */
211 config xdc.runtime.Assert.Id A_nullObject =
212 {msg: "A_nullObject: HeapTrack_printHeap called with null obj"};
213
214 instance:
215
216 /*!
217 * ======== internalHeap ========
218 * Heap to use with HeapTrack
219 */
220 config IHeap.Handle heap = null;
221
222 /*!
223 * ======== printHeap ========
224 * Print details for a HeapTrack instance
225 *
226 * Print the details of all allocated blocks of memory for a HeapTrack
227 * instance. This function is not thread safe.
228 */
229 Void printHeap();
230
231 internal:
232
233 234 235 236 237
238 const UArg NOSCRIBBLE = 0x05101920;
239
240 241 242 243
244 Bool printTrack(Tracker *tracker, Handle handle);
245
246
247 struct Instance_State {
248 IHeap.Handle internalHeap;
249 ti.sysbios.knl.Queue.Object trackQueue;
250 SizeT size;
251 SizeT peak;
252 SizeT sizeWithoutTracker;
253 SizeT peakWithoutTracker;
254 };
255 }