1 /*
2 * Percepio 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 for strings.
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 #include <trcTypes.h>
18
19 #ifndef TRC_SEND_NAME_ONLY_ON_DELETE
20 #define TRC_SEND_NAME_ONLY_ON_DELETE 0
21 #endif
22
23 traceResult prvTraceObjectSendNameEvent(void* pvObject, const char* szName);
24
xTraceObjectRegisterInternal(uint32_t uiEventCode,void * pvObject,const char * szName,TraceUnsignedBaseType_t uxStateCount,TraceUnsignedBaseType_t uxStates[],TraceUnsignedBaseType_t uxOptions,TraceObjectHandle_t * pxObjectHandle)25 traceResult xTraceObjectRegisterInternal(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxStateCount, TraceUnsignedBaseType_t uxStates[], TraceUnsignedBaseType_t uxOptions, TraceObjectHandle_t* pxObjectHandle)
26 {
27 TraceEntryHandle_t xEntryHandle;
28 TraceEventHandle_t xEventHandle = 0;
29 TraceUnsignedBaseType_t i;
30
31 TRACE_ALLOC_CRITICAL_SECTION();
32
33 /* This should never fail */
34 TRC_ASSERT(pxObjectHandle != 0);
35
36 /* This should never fail */
37 TRC_ASSERT(uxStateCount <= (TRC_ENTRY_TABLE_STATE_COUNT));
38
39 TRACE_ENTER_CRITICAL_SECTION();
40
41 if (pvObject != 0)
42 {
43 /* An address was supplied */
44 if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
45 {
46 TRACE_EXIT_CRITICAL_SECTION();
47
48 return TRC_FAIL;
49 }
50 }
51 else
52 {
53 /* No address was supplied */
54 if (xTraceEntryCreate(&xEntryHandle) == TRC_FAIL)
55 {
56 TRACE_EXIT_CRITICAL_SECTION();
57
58 return TRC_FAIL;
59 }
60
61 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress(xEntryHandle, &pvObject) == TRC_SUCCESS);
62 }
63
64 for (i = 0; i < uxStateCount; i++)
65 {
66 /* This should never fail */
67 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetState(xEntryHandle, i, uxStates[i]) == TRC_SUCCESS);
68 }
69
70 /* This should never fail */
71 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntrySetOptions(xEntryHandle, uxOptions) == TRC_SUCCESS);
72
73 *pxObjectHandle = (TraceObjectHandle_t)xEntryHandle;
74
75 TRACE_EXIT_CRITICAL_SECTION();
76
77 if (szName != 0 && szName[0] != 0)
78 {
79 /* Not a null or empty string */
80 /* This will set the symbol and create an event for it */
81 /* This should never fail */
82 TRC_ASSERT_ALWAYS_EVALUATE(xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName) == TRC_SUCCESS);
83 }
84
85 /* Send the create event, if possible */
86 /*We need to check this */
87 if (xTraceEventBegin(uiEventCode, sizeof(void*) + uxStateCount * sizeof(TraceUnsignedBaseType_t), &xEventHandle) == TRC_SUCCESS)
88 {
89 xTraceEventAddPointer(xEventHandle, pvObject);
90 for (i = 0; i < uxStateCount; i++)
91 {
92 xTraceEventAddUnsignedBaseType(xEventHandle, uxStates[i]);
93 }
94 xTraceEventEnd(xEventHandle);
95 }
96
97 return TRC_SUCCESS;
98 }
99
xTraceObjectRegister(uint32_t uiEventCode,void * pvObject,const char * szName,TraceUnsignedBaseType_t uxState,TraceObjectHandle_t * pxObjectHandle)100 traceResult xTraceObjectRegister(uint32_t uiEventCode, void *pvObject, const char* szName, TraceUnsignedBaseType_t uxState, TraceObjectHandle_t *pxObjectHandle)
101 {
102 return xTraceObjectRegisterInternal(uiEventCode, pvObject, szName, 1, &uxState, 0, pxObjectHandle);
103 }
104
xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle,uint32_t uiEventCode,TraceUnsignedBaseType_t uxState)105 traceResult xTraceObjectUnregister(TraceObjectHandle_t xObjectHandle, uint32_t uiEventCode, TraceUnsignedBaseType_t uxState)
106 {
107 void* pvObject = 0;
108 const char *szName = 0;
109 TraceEventHandle_t xEventHandle = 0;
110
111 /* If asserts are disabled this variable will not get used, this stops warnings. */
112 (void)szName;
113
114 /* This should never fail */
115 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS);
116
117 /* This should never fail */
118 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetSymbol((TraceEntryHandle_t)xObjectHandle, &szName) == TRC_SUCCESS);
119
120 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 1)
121 /* Send name event because this is a delete */
122 /* This should never fail */
123 TRC_ASSERT(prvTraceObjectSendNameEvent(pvObject, szName) == TRC_SUCCESS);
124 #endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 1) */
125
126 /* Send the delete event, if possible */
127 if (xTraceEventBegin(uiEventCode, sizeof(void*) + sizeof(TraceUnsignedBaseType_t), &xEventHandle) == TRC_SUCCESS)
128 {
129 xTraceEventAddPointer(xEventHandle, pvObject);
130 xTraceEventAddUnsignedBaseType(xEventHandle, uxState);
131 xTraceEventEnd(xEventHandle);
132 }
133
134 return xTraceEntryDelete(xObjectHandle);
135 }
136
xTraceObjectSetName(TraceObjectHandle_t xObjectHandle,const char * szName)137 traceResult xTraceObjectSetName(TraceObjectHandle_t xObjectHandle, const char* szName)
138 {
139 void* pvObject = 0;
140
141 /* If asserts are disabled this variable will not get used, this stops warnings. */
142 (void)pvObject;
143
144 if (szName == 0)
145 {
146 szName = "";
147 }
148
149 /* This should never fail */
150 TRC_ASSERT_ALWAYS_EVALUATE(xTraceEntryGetAddress((TraceEntryHandle_t)xObjectHandle, &pvObject) == TRC_SUCCESS);
151
152 #if (TRC_SEND_NAME_ONLY_ON_DELETE == 0)
153 /* Send name event now since we don't do it on delete events */
154 /* This should never fail */
155 TRC_ASSERT_ALWAYS_EVALUATE(prvTraceObjectSendNameEvent(pvObject, szName) == TRC_SUCCESS);
156 #endif /* (TRC_SEND_NAME_ONLY_ON_DELETE == 0) */
157
158 return xTraceEntrySetSymbol((TraceEntryHandle_t)xObjectHandle, szName);
159 }
160
xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode,void * pvObject,const char * szName,TraceUnsignedBaseType_t uxState)161 traceResult xTraceObjectRegisterWithoutHandle(uint32_t uiEventCode, void* pvObject, const char* szName, TraceUnsignedBaseType_t uxState)
162 {
163 TraceObjectHandle_t xObjectHandle;
164
165 return xTraceObjectRegister(uiEventCode, pvObject, szName, uxState, &xObjectHandle);
166 }
167
xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode,void * pvObject,TraceUnsignedBaseType_t uxState)168 traceResult xTraceObjectUnregisterWithoutHandle(uint32_t uiEventCode, void* pvObject, TraceUnsignedBaseType_t uxState)
169 {
170 TraceEntryHandle_t xEntryHandle;
171 traceResult xResult;
172
173 TRACE_ALLOC_CRITICAL_SECTION();
174
175 TRACE_ENTER_CRITICAL_SECTION();
176
177 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
178 {
179 TRACE_EXIT_CRITICAL_SECTION();
180
181 return TRC_FAIL;
182 }
183
184 xResult = xTraceObjectUnregister((TraceObjectHandle_t)xEntryHandle, uiEventCode, uxState);
185
186 TRACE_EXIT_CRITICAL_SECTION();
187
188 return xResult;
189 }
190
xTraceObjectSetNameWithoutHandle(void * pvObject,const char * szName)191 traceResult xTraceObjectSetNameWithoutHandle(void* pvObject, const char* szName)
192 {
193 TraceEntryHandle_t xEntryHandle;
194 traceResult xResult;
195
196 TRACE_ALLOC_CRITICAL_SECTION();
197
198 TRACE_ENTER_CRITICAL_SECTION();
199
200 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
201 {
202 /* No previous entry found. Create one. */
203 if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
204 {
205 TRACE_EXIT_CRITICAL_SECTION();
206
207 return TRC_FAIL;
208 }
209 }
210
211 xResult = xTraceObjectSetName((TraceObjectHandle_t)xEntryHandle, szName);
212
213 TRACE_EXIT_CRITICAL_SECTION();
214
215 return xResult;
216 }
217
xTraceObjectSetSpecificStateWithoutHandle(void * pvObject,uint32_t uiIndex,TraceUnsignedBaseType_t uxState)218 traceResult xTraceObjectSetSpecificStateWithoutHandle(void* pvObject, uint32_t uiIndex, TraceUnsignedBaseType_t uxState)
219 {
220 TraceEntryHandle_t xEntryHandle;
221 traceResult xResult;
222
223 TRACE_ALLOC_CRITICAL_SECTION();
224
225 TRACE_ENTER_CRITICAL_SECTION();
226
227 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
228 {
229 TRACE_EXIT_CRITICAL_SECTION();
230
231 return TRC_FAIL;
232 }
233
234 xResult = xTraceObjectSetSpecificState((TraceObjectHandle_t)xEntryHandle, uiIndex, uxState);
235
236 TRACE_EXIT_CRITICAL_SECTION();
237
238 return xResult;
239 }
240
xTraceObjectSetOptionsWithoutHandle(void * pvObject,uint32_t uiMask)241 traceResult xTraceObjectSetOptionsWithoutHandle(void* pvObject, uint32_t uiMask)
242 {
243 TraceEntryHandle_t xEntryHandle;
244 traceResult xResult;
245
246 TRACE_ALLOC_CRITICAL_SECTION();
247
248 TRACE_ENTER_CRITICAL_SECTION();
249
250 if (xTraceEntryFind(pvObject, &xEntryHandle) == TRC_FAIL)
251 {
252 /* No previous entry found. Create one. */
253 if (xTraceEntryCreateWithAddress(pvObject, &xEntryHandle) == TRC_FAIL)
254 {
255 TRACE_EXIT_CRITICAL_SECTION();
256
257 return TRC_FAIL;
258 }
259 }
260
261 xResult = xTraceObjectSetOptions((TraceObjectHandle_t)xEntryHandle, uiMask);
262
263 TRACE_EXIT_CRITICAL_SECTION();
264
265 return xResult;
266 }
267
prvTraceObjectSendNameEvent(void * pvObject,const char * szName)268 traceResult prvTraceObjectSendNameEvent(void* pvObject, const char* szName)
269 {
270 uint32_t i = 0, uiLength = 0, uiValue = 0;
271 TraceEventHandle_t xEventHandle = 0;
272
273 for (i = 0; (szName[i] != 0) && (i < (TRC_ENTRY_TABLE_SLOT_SYMBOL_SIZE)); i++) {}
274
275 uiLength = i;
276
277 if (xTraceEventBegin(PSF_EVENT_OBJ_NAME, sizeof(void*) + uiLength, &xEventHandle) == TRC_SUCCESS)
278 {
279 xTraceEventAddPointer(xEventHandle, pvObject);
280 xTraceEventAddData(xEventHandle, (void*)szName, uiLength);
281
282 /* Check if we can truncate */
283 xTraceEventPayloadRemaining(xEventHandle, &uiValue);
284 if (uiValue > 0)
285 {
286 xTraceEventAdd8(xEventHandle, 0);
287 }
288
289 xTraceEventEnd(xEventHandle);
290 }
291
292 return TRC_SUCCESS;
293 }
294
295 #endif /* (TRC_CFG_RECORDER_MODE == TRC_RECORDER_MODE_STREAMING) */
296
297 #endif /* (TRC_USE_TRACEALYZER_RECORDER == 1) */
298