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