1 /*
2 * Trace Recorder for Tracealyzer v4.8.1
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)
14 
15 #if (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING)
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(xIndex < (TraceEntryIndex_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 	uint32_t i;
198 
199 	/* This should never fail */
200 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
201 
202 	if (szSymbol == (void*)0)
203 	{
204 		szSymbol = ""; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
205 		uiLength = 0u; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
206 	}
207 
208 	/* Remember the longest symbol name */
209 	(void)xTraceDiagnosticsSetIfHigher(TRC_DIAGNOSTICS_ENTRY_SYMBOL_LONGEST_LENGTH, (int32_t)uiLength);
210 
211 	if (uiLength >= (uint32_t)(TRC_ENTRY_TABLE_SYMBOL_LENGTH))
212 	{
213 		/* No room for null termination. Set to max. */
214 		uiLength = (uint32_t)(TRC_ENTRY_TABLE_SYMBOL_LENGTH) / sizeof(uint32_t); /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
215 	}
216 	else
217 	{
218 		/* Make room for null termination by increasing the number of uint32_t required by 1 */
219 		uiLength = (uiLength / sizeof(uint32_t)) + 1u; /*cstat !MISRAC2012-Rule-17.8 Suppress modified function parameter check*/
220 	}
221 
222 	/* Does not need to be locked. */
223 	/* This should never fail */
224 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
225 
226 	/* This will also copy the null termination, if possible */
227 	for (i = 0u; i < uiLength; i++)
228 	{
229 		((uint32_t*)(((TraceEntry_t*)xEntryHandle)->szSymbol))[i] = ((const uint32_t*)szSymbol)[i];  /*cstat !MISRAC2004-11.4 !MISRAC2012-Rule-11.3 Suppress conversion between pointer types checks*/ /*cstat !MISRAC2004-17.4_b We cast it to a uint32_t* in order to copy 4 bytes at a time*/
230 	}
231 
232 	return TRC_SUCCESS;
233 }
234 
xTraceEntryGetCount(uint32_t * puiCount)235 traceResult xTraceEntryGetCount(uint32_t* puiCount)
236 {
237 	/* This should never fail */
238 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
239 
240 	/* This should never fail */
241 	TRC_ASSERT(puiCount != (void*)0);
242 
243 	*puiCount = (uint32_t)(TRC_ENTRY_TABLE_SLOTS) - GET_FREE_INDEX_COUNT();
244 
245 	return TRC_SUCCESS;
246 }
247 
xTraceEntryGetAtIndex(uint32_t index,TraceEntryHandle_t * pxEntryHandle)248 traceResult xTraceEntryGetAtIndex(uint32_t index, TraceEntryHandle_t* pxEntryHandle)
249 {
250 	/* This should never fail */
251 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
252 
253 	/* This should never fail */
254 	TRC_ASSERT(index < (uint32_t)(TRC_ENTRY_TABLE_SLOTS));
255 
256 	/* This should never fail */
257 	TRC_ASSERT(pxEntryHandle != (void*)0);
258 
259 	*pxEntryHandle = (TraceEntryHandle_t)&pxEntryTable->axEntries[index];
260 
261 	return TRC_SUCCESS;
262 }
263 
264 #if ((TRC_CFG_USE_TRACE_ASSERT) == 1)
265 
xTraceEntryCreateWithAddress(void * const pvAddress,TraceEntryHandle_t * pxEntryHandle)266 traceResult xTraceEntryCreateWithAddress(void* const pvAddress, TraceEntryHandle_t* pxEntryHandle)
267 {
268 	/* This should never fail */
269 	TRC_ASSERT(pvAddress != (void*)0);
270 
271 	return TRC_ENTRY_CREATE_WITH_ADDRESS(pvAddress, pxEntryHandle);
272 }
273 
xTraceEntrySetState(const TraceEntryHandle_t xEntryHandle,TraceUnsignedBaseType_t uxStateIndex,TraceUnsignedBaseType_t uxState)274 traceResult xTraceEntrySetState(const TraceEntryHandle_t xEntryHandle, TraceUnsignedBaseType_t uxStateIndex, TraceUnsignedBaseType_t uxState)
275 {
276 	/* This should never fail */
277 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
278 
279 	/* This should never fail */
280 	TRC_ASSERT(uxStateIndex < (TraceUnsignedBaseType_t)(TRC_ENTRY_TABLE_STATE_COUNT));
281 
282 	/* This should never fail */
283 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
284 
285 	return TRC_ENTRY_SET_STATE(xEntryHandle, uxStateIndex, uxState);
286 }
287 
xTraceEntrySetOptions(const TraceEntryHandle_t xEntryHandle,uint32_t uiMask)288 traceResult xTraceEntrySetOptions(const TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
289 {
290 	/* This should never fail */
291 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
292 
293 	/* Does not need to be locked. */
294 	/* This should never fail */
295 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
296 
297 	return TRC_ENTRY_SET_OPTIONS(xEntryHandle, uiMask);
298 }
299 
xTraceEntryClearOptions(const TraceEntryHandle_t xEntryHandle,uint32_t uiMask)300 traceResult xTraceEntryClearOptions(const TraceEntryHandle_t xEntryHandle, uint32_t uiMask)
301 {
302 	/* This should never fail */
303 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
304 
305 	/* Does not need to be locked. */
306 	/* This should never fail */
307 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
308 
309 	return TRC_ENTRY_CLEAR_OPTIONS(xEntryHandle, uiMask);
310 }
311 
xTraceEntryGetAddress(const TraceEntryHandle_t xEntryHandle,void ** ppvAddress)312 traceResult xTraceEntryGetAddress(const TraceEntryHandle_t xEntryHandle, void **ppvAddress)
313 {
314 	/* This should never fail */
315 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
316 
317 	/* This should never fail */
318 	TRC_ASSERT(ppvAddress != (void*)0);
319 
320 	/* Does not need to be locked. */
321 	/* This should never fail */
322 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
323 
324 	return TRC_ENTRY_GET_ADDRESS(xEntryHandle, ppvAddress);
325 }
326 
327 /*cstat !MISRAC2004-6.3 !MISRAC2012-Dir-4.6_a Suppress basic char type usage*/
xTraceEntryGetSymbol(const TraceEntryHandle_t xEntryHandle,const char ** pszSymbol)328 traceResult xTraceEntryGetSymbol(const TraceEntryHandle_t xEntryHandle, const char** pszSymbol)
329 {
330 	/* This should never fail */
331 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
332 
333 	/* This should never fail */
334 	TRC_ASSERT(pszSymbol != (void*)0);
335 
336 	/* Does not need to be locked. */
337 	/* This should never fail */
338 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
339 
340 	return TRC_ENTRY_GET_SYMBOL(xEntryHandle, pszSymbol);
341 }
342 
xTraceEntryGetState(const TraceEntryHandle_t xEntryHandle,TraceUnsignedBaseType_t uxStateIndex,TraceUnsignedBaseType_t * puxState)343 traceResult xTraceEntryGetState(const TraceEntryHandle_t xEntryHandle, TraceUnsignedBaseType_t uxStateIndex, TraceUnsignedBaseType_t *puxState)
344 {
345 	/* This should never fail */
346 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
347 
348 	/* This should never fail */
349 	TRC_ASSERT(puxState != (void*)0);
350 
351 	/* This should never fail */
352 	TRC_ASSERT(uxStateIndex < (TraceUnsignedBaseType_t)(TRC_ENTRY_TABLE_STATE_COUNT));
353 
354 	/* Does not need to be locked. */
355 	/* This should never fail */
356 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
357 
358 	return TRC_ENTRY_GET_STATE(xEntryHandle, uxStateIndex, puxState);
359 }
360 
361 /*cstat !MISRAC2012-Rule-8.13 Suppress const check for xEntryHandle*/
xTraceEntryGetStateReturn(const TraceEntryHandle_t xEntryHandle,TraceUnsignedBaseType_t uxStateIndex)362 TraceUnsignedBaseType_t xTraceEntryGetStateReturn(const TraceEntryHandle_t xEntryHandle, TraceUnsignedBaseType_t uxStateIndex)
363 {
364 	return TRC_ENTRY_GET_STATE_RETURN(xEntryHandle, uxStateIndex);
365 }
366 
xTraceEntryGetOptions(const TraceEntryHandle_t xEntryHandle,uint32_t * puiOptions)367 traceResult xTraceEntryGetOptions(const TraceEntryHandle_t xEntryHandle, uint32_t *puiOptions)
368 {
369 	/* This should never fail */
370 	TRC_ASSERT(xTraceIsComponentInitialized(TRC_RECORDER_COMPONENT_ENTRY));
371 
372 	/* This should never fail */
373 	TRC_ASSERT(puiOptions != (void*)0);
374 
375 	/* Does not need to be locked. */
376 	/* This should never fail */
377 	TRC_ASSERT(VALIDATE_ENTRY_HANDLE(xEntryHandle)); /*cstat !MISRAC2004-17.3 !MISRAC2012-Rule-18.3 Suppress pointer comparison check*/
378 
379 	return TRC_ENTRY_GET_OPTIONS(xEntryHandle, puiOptions);
380 }
381 
382 #endif /* ((TRC_CFG_USE_TRACE_ASSERT) == 1) */
383 
384 /* PRIVATE FUNCTIONS */
385 
prvEntryIndexInitialize(void)386 static traceResult prvEntryIndexInitialize(void)
387 {
388 	uint32_t i;
389 
390 	for (i = 0u; i < (uint32_t)(TRC_ENTRY_TABLE_SLOTS); i++)
391 	{
392 		pxIndexTable->axFreeIndexes[i] = (TraceEntryIndex_t)i;
393 	}
394 
395 	pxIndexTable->uiFreeIndexCount = TRC_ENTRY_TABLE_SLOTS;
396 
397 	return TRC_SUCCESS;
398 }
399 
prvEntryIndexTake(TraceEntryIndex_t * pxIndex)400 static traceResult prvEntryIndexTake(TraceEntryIndex_t *pxIndex)
401 {
402 	/* Critical Section must be active! */
403 	TraceEntryIndex_t xIndex;
404 
405 	if (pxIndexTable->uiFreeIndexCount == 0u)
406 	{
407 		return TRC_FAIL;
408 	}
409 
410 	/* Always take the first item */
411 	xIndex = pxIndexTable->axFreeIndexes[0];
412 	pxIndexTable->uiFreeIndexCount--;
413 
414 	/* Move the last item to the first slot, to avoid holes */
415 	pxIndexTable->axFreeIndexes[0] = pxIndexTable->axFreeIndexes[pxIndexTable->uiFreeIndexCount];
416 
417 #if (TRC_ENTRY_TABLE_SLOTS > 256)
418 	pxIndexTable->axFreeIndexes[pxIndexTable->uiFreeIndexCount] = UINT16_MAX;
419 #else
420 	pxIndexTable->axFreeIndexes[pxIndexTable->uiFreeIndexCount] = UINT8_MAX;
421 #endif
422 
423 	*pxIndex = xIndex;
424 	return TRC_SUCCESS;
425 }
426 
427 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
428 
429 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
430