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