1 /*
2 * Trace Recorder for Tracealyzer v4.6.6
3 * Copyright 2021 Percepio AB
4 * www.percepio.com
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * The implementation of the entry table.
9 */
10 
11 #include <trcRecorder.h>
12 
13 #if (TRC_USE_TRACEALYZER_RECORDER == 1)
14 
15 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
16 
17 #define VALIDATE_ENTRY_HANDLE(xEntryHandle) ((((TraceUnsignedBaseType_t)(xEntryHandle) >= (TraceUnsignedBaseType_t)pxEntryTable) && ((TraceUnsignedBaseType_t)(xEntryHandle) < ((TraceUnsignedBaseType_t)pxEntryTable + sizeof(TraceEntryTable_t)))))
18 
19 #define GIVE_ENTRY_INDEX(xIndex) xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = (xIndex); xIndexTable.uiFreeIndexCount++
20 
21 #define GET_FREE_INDEX_COUNT() xIndexTable.uiFreeIndexCount
22 
23 #define CALCULATE_ENTRY_INDEX(xEntryHandle) (TraceEntryIndex_t)(((TraceUnsignedBaseType_t)((TraceUnsignedBaseType_t)(xEntryHandle) - (TraceUnsignedBaseType_t)pxEntryTable) / sizeof(TraceEntry_t)))
24 
25 #if (TRC_ENTRY_TABLE_SLOTS > 256)
26 typedef uint16_t TraceEntryIndex_t;
27 #else
28 typedef uint8_t TraceEntryIndex_t;
29 #endif /* (TRC_CFG_ENTRY_TABLE_SLOTS > 256) */
30 
31 typedef struct EntryIndexTable
32 {
33 	TraceEntryIndex_t axFreeIndexes[TRC_ENTRY_TABLE_SLOTS];
34 	uint32_t uiFreeIndexCount;
35 } TraceEntryIndexTable_t;
36 
37 typedef struct TraceEntryTable
38 {
39 	uint32_t uiSlots;
40 	uint32_t uiEntrySymbolLength;
41 	uint32_t uiEntryStateCount;
42 	TraceEntry_t axEntries[TRC_ENTRY_TABLE_SLOTS];
43 } TraceEntryTable_t;
44 
45 /* Private function definitions */
46 traceResult prvEntryIndexInitialize(TraceEntryIndexTable_t *pxIndexTable);
47 traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex);
48 
49 /* Variables */
50 static TraceEntryTable_t *pxEntryTable;
51 static TraceEntryIndexTable_t xIndexTable;
52 
xTraceEntryTableInitialize(TraceEntryTableBuffer_t * pxBuffer)53 traceResult xTraceEntryTableInitialize(TraceEntryTableBuffer_t *pxBuffer)
54 {
55 	uint32_t i, j;
56 
57 	TRC_ASSERT_EQUAL_SIZE(TraceEntryTableBuffer_t, TraceEntryTable_t);
58 
59 	/* This should never fail */
60 	TRC_ASSERT(pxBuffer != 0);
61 
62 	/* This should never fail */
63 	TRC_ASSERT((TRC_ENTRY_TABLE_SLOTS) != 0);
64 
65 	pxEntryTable = (TraceEntryTable_t*)pxBuffer;
66 
67 	pxEntryTable->uiSlots = TRC_ENTRY_TABLE_SLOTS;
68 	pxEntryTable->uiEntrySymbolLength = TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE;
69 	pxEntryTable->uiEntryStateCount = TRC_ENTRY_TABLE_STATE_COUNT;
70 
71 	for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++)
72 	{
73 		pxEntryTable->axEntries[i].pvAddress = 0;
74 		for (j = 0; j < TRC_ENTRY_TABLE_STATE_COUNT; j++)
75 		{
76 			pxEntryTable->axEntries[i].xStates[j] = 0;
77 		}
78 		pxEntryTable->axEntries[i].szSymbol[0] = 0;
79 	}
80 
81 	prvEntryIndexInitialize(&xIndexTable);
82 
83 	xTraceSetComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY);
84 
85 	return TRC_SUCCESS;
86 }
87 
xTraceEntryCreate(TraceEntryHandle_t * pxEntryHandle)88 traceResult xTraceEntryCreate(TraceEntryHandle_t *pxEntryHandle)
89 {
90 	uint32_t i;
91 	TraceEntryIndex_t xIndex;
92 	TraceEntry_t *pxEntry;
93 
94 	TRACE_ALLOC_CRITICAL_SECTION();
95 
96 	/* We always check this */
97 	if (!xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY))
98 	{
99 		return TRC_FAIL;
100 	}
101 
102 	/* This should never fail */
103 	TRC_ASSERT(pxEntryHandle != 0);
104 
105 	TRACE_ENTER_CRITICAL_SECTION();
106 
107 	if (prvEntryIndexTake(&xIndex) != TRC_SUCCESS)
108 	{
109 		xTraceDiagnosticsIncrease(TRC_DIAGNOSTICS_ENTRY_SLOTS_NO_ROOM);
110 
111 		TRACE_EXIT_CRITICAL_SECTION();
112 
113 		return TRC_FAIL;
114 	}
115 
116 	pxEntry = &pxEntryTable->axEntries[xIndex];
117 
118 	pxEntry->pvAddress = (void*)pxEntry; /* We set a temporary address */
119 
120 	for (i = 0; i < TRC_ENTRY_TABLE_STATE_COUNT; i++)
121 	{
122 		pxEntry->xStates[i] = 0;
123 	}
124 
125 	pxEntry->uiOptions = 0;
126 	pxEntry->szSymbol[0] = 0;
127 
128 	*pxEntryHandle = (TraceEntryHandle_t)pxEntry;
129 
130 	TRACE_EXIT_CRITICAL_SECTION();
131 
132 	return TRC_SUCCESS;
133 }
134 
xTraceEntryDelete(TraceEntryHandle_t xEntryHandle)135 traceResult xTraceEntryDelete(TraceEntryHandle_t xEntryHandle)
136 {
137 	TraceEntryIndex_t xIndex;
138 
139 	TRACE_ALLOC_CRITICAL_SECTION();
140 
141 	/* This should never fail */
142 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
143 
144 	/* This should never fail */
145 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
146 
147 	/* Calculate the index based on the entry address */
148 	/* Does not need to be locked. */
149 	/* This should never fail */
150 	xIndex = CALCULATE_ENTRY_INDEX(xEntryHandle);
151 
152 	TRC_ASSERT(xIndex < TRC_ENTRY_TABLE_SLOTS);
153 
154 	TRACE_ENTER_CRITICAL_SECTION();
155 
156 	if (((TraceEntry_t*)xEntryHandle)->pvAddress == 0)
157 	{
158 		/* Someone else has deleted this already? */
159 		TRACE_EXIT_CRITICAL_SECTION();
160 
161 		return TRC_FAIL;
162 	}
163 
164 	/* A valid address, so we assume it is OK. */
165 	/* For good measure, we clear the address field */
166 	((TraceEntry_t*)xEntryHandle)->pvAddress = 0;
167 
168 	/* Give back the index */
169 	GIVE_ENTRY_INDEX(xIndex);
170 
171 	TRACE_EXIT_CRITICAL_SECTION();
172 
173 	return TRC_SUCCESS;
174 }
175 
xTraceEntryFind(void * pvAddress,TraceEntryHandle_t * pxEntryHandle)176 traceResult xTraceEntryFind(void* pvAddress, TraceEntryHandle_t* pxEntryHandle)
177 {
178 	uint32_t i;
179 	TraceEntry_t* pxEntry;
180 
181 	/* This should never fail */
182 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
183 
184 	/* This should never fail */
185 	TRC_ASSERT(pxEntryHandle != 0);
186 
187 	/* This should never fail */
188 	TRC_ASSERT(pvAddress != 0);
189 
190 	for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++)
191 	{
192 		pxEntry = (TraceEntry_t*)(((uint32_t)pxEntryTable->axEntries) + (i * sizeof(TraceEntry_t)));
193 		if (pxEntry->pvAddress == pvAddress)
194 		{
195 			*pxEntryHandle = (TraceEntryHandle_t)pxEntry;
196 
197 			return TRC_SUCCESS;
198 		}
199 	}
200 
201 	return TRC_FAIL;
202 }
203 
xTraceEntrySetSymbol(TraceEntryHandle_t xEntryHandle,const char * szSymbol)204 traceResult xTraceEntrySetSymbol(TraceEntryHandle_t xEntryHandle, const char* szSymbol)
205 {
206 	uint32_t i;
207 
208 	/* This should never fail */
209 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
210 
211 	if (szSymbol == 0)
212 	{
213 		szSymbol = "";
214 	}
215 
216 	/* Does not need to be locked. */
217 	/* This should never fail */
218 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
219 
220 	for (i = 0; i < (TRC_ENTRY_TABLE_SYMBOL_LENGTH); i++)
221 	{
222 		((TraceEntry_t*)xEntryHandle)->szSymbol[i] = szSymbol[i];	/* We do this first to ensure we also get the 0 termination, if there is one */
223 
224 		if (szSymbol[i] == 0)
225 		{
226 			break;
227 		}
228 	}
229 
230 	/* Check the length of "name", if longer than TRC_ENTRY_TABLE_SYMBOL_LENGTH */
231 	while ((szSymbol[i] != 0) && i < 128)
232 	{
233 		i++;
234 	}
235 
236 	/* Remember the longest symbol name */
237 	xTraceDiagnosticsSetIfHigher(TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH, i);
238 
239 	return TRC_SUCCESS;
240 }
241 
xTraceEntryGetCount(uint32_t * puiCount)242 traceResult xTraceEntryGetCount(uint32_t* puiCount)
243 {
244 	/* This should never fail */
245 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
246 
247 	/* This should never fail */
248 	TRC_ASSERT(puiCount != 0);
249 
250 	*puiCount = TRC_ENTRY_TABLE_SLOTS - GET_FREE_INDEX_COUNT();
251 
252 	return TRC_SUCCESS;
253 }
254 
xTraceEntryGetAtIndex(uint32_t index,TraceEntryHandle_t * pxEntryHandle)255 traceResult xTraceEntryGetAtIndex(uint32_t index, TraceEntryHandle_t* pxEntryHandle)
256 {
257 	/* This should never fail */
258 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
259 
260 	/* This should never fail */
261 	TRC_ASSERT(index < TRC_ENTRY_TABLE_SLOTS);
262 
263 	/* This should never fail */
264 	TRC_ASSERT(pxEntryHandle != 0);
265 
266 	*pxEntryHandle = (TraceEntryHandle_t)((uint32_t)(pxEntryTable->axEntries) + (index * sizeof(TraceEntry_t)));
267 
268 	return TRC_SUCCESS;
269 }
270 
271 #if ((TRC_CFG_USE_TRACE_ASSERT) == 1)
272 
xTraceEntryCreateWithAddress(void * pvAddress,TraceEntryHandle_t * pxEntryHandle)273 traceResult xTraceEntryCreateWithAddress(void* pvAddress, TraceEntryHandle_t* pxEntryHandle)
274 {
275 	/* This should never fail */
276 	TRC_ASSERT(pvAddress != 0);
277 
278 	return TRC_ENTRY_CREATE_WITH_ADDRESS(pvAddress, pxEntryHandle);
279 }
280 
xTraceEntrySetState(TraceEntryHandle_t xEntryHandle,uint32_t uiStateIndex,TraceUnsignedBaseType_t uxState)281 traceResult xTraceEntrySetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t uxState)
282 {
283 	/* This should never fail */
284 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
285 
286 	/* This should never fail */
287 	TRC_ASSERT(uiStateIndex < (TRC_ENTRY_TABLE_STATE_COUNT));
288 
289 	/* This should never fail */
290 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
291 
292 	return TRC_ENTRY_SET_STATE(xEntryHandle, uiStateIndex, uxState);
293 }
294 
xTraceEntrySetOptions(TraceEntryHandle_t xEntryHandle,uint32_t uiMask)295 traceResult xTraceEntrySetOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
296 {
297 	/* This should never fail */
298 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
299 
300 	/* Does not need to be locked. */
301 	/* This should never fail */
302 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
303 
304 	return TRC_ENTRY_SET_OPTIONS(xEntryHandle, uiMask);
305 }
306 
xTraceEntryClearOptions(TraceEntryHandle_t xEntryHandle,uint32_t uiMask)307 traceResult xTraceEntryClearOptions(TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
308 {
309 	/* This should never fail */
310 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
311 
312 	/* Does not need to be locked. */
313 	/* This should never fail */
314 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
315 
316 	return TRC_ENTRY_CLEAR_OPTIONS(xEntryHandle, uiMask);
317 }
318 
xTraceEntryGetAddress(TraceEntryHandle_t xEntryHandle,void ** ppvAddress)319 traceResult xTraceEntryGetAddress(TraceEntryHandle_t xEntryHandle, void **ppvAddress)
320 {
321 	/* This should never fail */
322 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
323 
324 	/* This should never fail */
325 	TRC_ASSERT(ppvAddress != 0);
326 
327 	/* Does not need to be locked. */
328 	/* This should never fail */
329 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
330 
331 	return TRC_ENTRY_GET_ADDRESS(xEntryHandle, ppvAddress);
332 }
333 
xTraceEntryGetSymbol(TraceEntryHandle_t xEntryHandle,const char ** pszSymbol)334 traceResult xTraceEntryGetSymbol(TraceEntryHandle_t xEntryHandle, const char** pszSymbol)
335 {
336 	/* This should never fail */
337 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
338 
339 	/* This should never fail */
340 	TRC_ASSERT(pszSymbol != 0);
341 
342 	/* Does not need to be locked. */
343 	/* This should never fail */
344 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
345 
346 	return TRC_ENTRY_GET_SYMBOL(xEntryHandle, pszSymbol);
347 }
348 
xTraceEntryGetState(TraceEntryHandle_t xEntryHandle,uint32_t uiStateIndex,TraceUnsignedBaseType_t * puxState)349 traceResult xTraceEntryGetState(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex, TraceUnsignedBaseType_t *puxState)
350 {
351 	/* This should never fail */
352 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
353 
354 	/* This should never fail */
355 	TRC_ASSERT(puxState != 0);
356 
357 	/* This should never fail */
358 	TRC_ASSERT(uiStateIndex < TRC_ENTRY_TABLE_STATE_COUNT);
359 
360 	/* Does not need to be locked. */
361 	/* This should never fail */
362 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
363 
364 	return TRC_ENTRY_GET_STATE(xEntryHandle, uiStateIndex, puxState);
365 }
366 
xTraceEntryGetStateReturn(TraceEntryHandle_t xEntryHandle,uint32_t uiStateIndex)367 TraceUnsignedBaseType_t xTraceEntryGetStateReturn(TraceEntryHandle_t xEntryHandle, uint32_t uiStateIndex)
368 {
369 	return TRC_ENTRY_GET_STATE_RETURN(xEntryHandle, uiStateIndex);
370 }
371 
xTraceEntryGetOptions(TraceEntryHandle_t xEntryHandle,uint32_t * puiOptions)372 traceResult xTraceEntryGetOptions(TraceEntryHandle_t xEntryHandle, uint32_t *puiOptions)
373 {
374 	/* This should never fail */
375 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
376 
377 	/* This should never fail */
378 	TRC_ASSERT(puiOptions != 0);
379 
380 	/* Does not need to be locked. */
381 	/* This should never fail */
382 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle));
383 
384 	return TRC_ENTRY_GET_OPTIONS(xEntryHandle, puiOptions);
385 }
386 
387 #endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */
388 
389 /* PRIVATE FUNCTIONS */
390 
prvEntryIndexInitialize(TraceEntryIndexTable_t * pxIndexTable)391 traceResult prvEntryIndexInitialize(TraceEntryIndexTable_t* pxIndexTable)
392 {
393 	uint32_t i;
394 
395 	for (i = 0; i < TRC_ENTRY_TABLE_SLOTS; i++)
396 	{
397 		pxIndexTable->axFreeIndexes[i] = (TraceEntryIndex_t)i;
398 	}
399 
400 	xIndexTable.uiFreeIndexCount = TRC_ENTRY_TABLE_SLOTS;
401 
402 	return TRC_SUCCESS;
403 }
404 
prvEntryIndexTake(TraceEntryIndex_t * pxIndex)405 traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex)
406 {
407 	/* Critical Section must be active! */
408 	TraceEntryIndex_t xIndex;
409 
410 	if (xIndexTable.uiFreeIndexCount == 0)
411 	{
412 		return TRC_FAIL;
413 	}
414 
415 	/* Always take the first item */
416 	xIndex = xIndexTable.axFreeIndexes[0];
417 	xIndexTable.uiFreeIndexCount--;
418 
419 	/* Move the last item to the first slot, to avoid holes */
420 	xIndexTable.axFreeIndexes[0] = xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount];
421 
422 #if (TRC_ENTRY_TABLE_SLOTS > 256)
423 	xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = UINT16_MAX;
424 #else
425 	xIndexTable.axFreeIndexes[xIndexTable.uiFreeIndexCount] = UINT8_MAX;
426 #endif
427 
428 	*pxIndex = xIndex;
429 	return TRC_SUCCESS;
430 }
431 
432 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
433 
434 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
435