1 /***************************************************************************
2 * Copyright (c) 2024 Microsoft Corporation
3 *
4 * This program and the accompanying materials are made available under the
5 * terms of the MIT License which is available at
6 * https://opensource.org/licenses/MIT.
7 *
8 * SPDX-License-Identifier: MIT
9 **************************************************************************/
10
11
12 /**************************************************************************/
13 /**************************************************************************/
14 /** */
15 /** ThreadX Component */
16 /** */
17 /** Trace */
18 /** */
19 /**************************************************************************/
20 /**************************************************************************/
21
22 #define TX_SOURCE_CODE
23
24
25 /* Include necessary system files. */
26
27 #include "tx_api.h"
28 #include "tx_trace.h"
29
30
31 /**************************************************************************/
32 /* */
33 /* FUNCTION RELEASE */
34 /* */
35 /* _tx_trace_object_register PORTABLE C */
36 /* 6.1.12 */
37 /* AUTHOR */
38 /* */
39 /* William E. Lamie, Microsoft Corporation */
40 /* */
41 /* DESCRIPTION */
42 /* */
43 /* This function registers a ThreadX system object in the trace */
44 /* registry area. This provides a mapping between the object pointers */
45 /* stored in each trace event to the actual ThreadX objects. */
46 /* */
47 /* INPUT */
48 /* */
49 /* object_type Type of system object */
50 /* object_ptr Address of system object */
51 /* object_name Name of system object */
52 /* parameter_1 Supplemental parameter 1 */
53 /* parameter_2 Supplemental parameter 2 */
54 /* */
55 /* OUTPUT */
56 /* */
57 /* None */
58 /* */
59 /* CALLS */
60 /* */
61 /* None */
62 /* */
63 /* CALLED BY */
64 /* */
65 /* Application Code */
66 /* */
67 /* RELEASE HISTORY */
68 /* */
69 /* DATE NAME DESCRIPTION */
70 /* */
71 /* 05-19-2020 William E. Lamie Initial Version 6.0 */
72 /* 09-30-2020 Yuxin Zhou Modified comment(s), */
73 /* resulting in version 6.1 */
74 /* 07-29-2022 Scott Larson Modified comment(s), */
75 /* check for null name, */
76 /* resulting in version 6.1.12 */
77 /* */
78 /**************************************************************************/
_tx_trace_object_register(UCHAR object_type,VOID * object_ptr,CHAR * object_name,ULONG parameter_1,ULONG parameter_2)79 VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2)
80 {
81
82 #ifdef TX_ENABLE_EVENT_TRACE
83
84 UINT i, entries;
85 UINT found, loop_break;
86 TX_THREAD *thread_ptr;
87 UCHAR *work_ptr;
88 TX_TRACE_OBJECT_ENTRY *entry_ptr;
89
90
91 /* Determine if the registry area is setup. */
92 if (_tx_trace_registry_start_ptr != TX_NULL)
93 {
94
95 /* Trace buffer is enabled, proceed. */
96
97 /* Pickup the total entries. */
98 entries = _tx_trace_total_registry_entries;
99
100 /* Determine if there are available entries in the registry. */
101 if (_tx_trace_available_registry_entries != ((ULONG) 0))
102 {
103
104 /* There are more available entries, proceed. */
105
106 /* Initialize found to the max entries... indicating no space was found. */
107 found = entries;
108 loop_break = TX_FALSE;
109
110 /* Loop to find available entry. */
111 i = _tx_trace_registry_search_start;
112 do
113 {
114
115 /* Setup the registry entry pointer. */
116 work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
117 work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*i));
118 entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
119
120 /* Determine if this is the first pass building the registry. A NULL object value indicates this part
121 of the registry has never been used. */
122 if (entry_ptr -> tx_trace_object_entry_thread_pointer == (ULONG) 0)
123 {
124
125 /* Set found to this index and break out of the loop. */
126 found = i;
127 loop_break = TX_TRUE;
128 }
129
130 /* Determine if this entry matches the object pointer... we must reuse old entries left in the
131 registry. */
132 if (entry_ptr -> tx_trace_object_entry_thread_pointer == TX_POINTER_TO_ULONG_CONVERT(object_ptr))
133 {
134
135 /* Set found to this index and break out of the loop. */
136 found = i;
137 loop_break = TX_TRUE;
138 }
139
140 /* Determine if we should break out of the loop. */
141 if (loop_break == TX_TRUE)
142 {
143
144 /* Yes, break out of the loop. */
145 break;
146 }
147
148 /* Is this entry available? */
149 if (entry_ptr -> tx_trace_object_entry_available == TX_TRUE)
150 {
151
152 /* Yes, determine if we have not already found an empty slot. */
153 if (found == entries)
154 {
155 found = i;
156 }
157 else
158 {
159
160 /* Setup a pointer to the found entry. */
161 work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
162 work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*found));
163 entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
164
165 if (entry_ptr -> tx_trace_object_entry_type != ((UCHAR) 0))
166 {
167 found = i;
168 }
169 }
170 }
171
172 /* Move to the next entry. */
173 i++;
174
175 /* Determine if we have wrapped the list. */
176 if (i >= entries)
177 {
178
179 /* Yes, wrap to the beginning of the list. */
180 i = ((ULONG) 0);
181 }
182
183 } while (i != _tx_trace_registry_search_start);
184
185 /* Now determine if an empty or reuse entry has been found. */
186 if (found < entries)
187 {
188
189 /* Decrement the number of available entries. */
190 _tx_trace_available_registry_entries--;
191
192 /* Adjust the search index to the next entry. */
193 if ((found + ((ULONG) 1)) < entries)
194 {
195
196 /* Start searching from the next index. */
197 _tx_trace_registry_search_start = found + ((ULONG) 1);
198 }
199 else
200 {
201
202 /* Reset the search to the beginning of the list. */
203 _tx_trace_registry_search_start = ((ULONG) 0);
204 }
205
206 /* Yes, an entry has been found... */
207
208 /* Build a pointer to the found entry. */
209 work_ptr = TX_OBJECT_TO_UCHAR_POINTER_CONVERT(_tx_trace_registry_start_ptr);
210 work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, ((sizeof(TX_TRACE_OBJECT_ENTRY))*found));
211 entry_ptr = TX_UCHAR_TO_OBJECT_POINTER_CONVERT(work_ptr);
212
213 /* Populate the found entry! */
214 entry_ptr -> tx_trace_object_entry_available = ((UCHAR) TX_FALSE);
215 entry_ptr -> tx_trace_object_entry_type = object_type;
216 entry_ptr -> tx_trace_object_entry_thread_pointer = TX_POINTER_TO_ULONG_CONVERT(object_ptr);
217 entry_ptr -> tx_trace_object_entry_param_1 = parameter_1;
218 entry_ptr -> tx_trace_object_entry_param_2 = parameter_2;
219
220 /* Loop to copy the object name string... */
221 for (i = ((ULONG) 0); i < (((ULONG) TX_TRACE_OBJECT_REGISTRY_NAME)-((ULONG) 1)); i++)
222 {
223
224 /* Setup work pointer to the object name character. */
225 work_ptr = TX_CHAR_TO_UCHAR_POINTER_CONVERT(object_name);
226 work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, i);
227
228 /* Determine if object_name (work_ptr) is null. */
229 if (work_ptr == TX_NULL)
230 {
231 break;
232 }
233
234 /* Copy a character of the name. */
235 entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) *work_ptr;
236
237 /* Determine if we are at the end. */
238 if (*work_ptr == ((UCHAR) 0))
239 {
240 break;
241 }
242 }
243
244 /* Null terminate the object string. */
245 entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) 0;
246
247 /* Determine if a thread object type is present. */
248 if (object_type == TX_TRACE_OBJECT_TYPE_THREAD)
249 {
250
251 /* Yes, a thread object is present. */
252
253 /* Setup a pointer to the thread. */
254 thread_ptr = TX_VOID_TO_THREAD_POINTER_CONVERT(object_ptr);
255
256 /* Store the thread's priority in the reserved bits. */
257 entry_ptr -> tx_trace_object_entry_reserved1 = ((UCHAR) 0x80) | ((UCHAR) (thread_ptr -> tx_thread_priority >> ((UCHAR) 8)));
258 entry_ptr -> tx_trace_object_entry_reserved2 = (UCHAR) (thread_ptr -> tx_thread_priority & ((UCHAR) 0xFF));
259 }
260 else
261 {
262
263 /* For all other objects, set the reserved bytes to 0. */
264 entry_ptr -> tx_trace_object_entry_reserved1 = ((UCHAR) 0);
265 entry_ptr -> tx_trace_object_entry_reserved2 = ((UCHAR) 0);
266 }
267 }
268 }
269 }
270 #else
271
272 TX_INTERRUPT_SAVE_AREA
273
274
275 /* Access input arguments just for the sake of lint, MISRA, etc. */
276 if (object_type != ((UCHAR) 0))
277 {
278
279 if (object_ptr != TX_NULL)
280 {
281
282 if (object_name != TX_NULL)
283 {
284
285 if (parameter_1 != ((ULONG) 0))
286 {
287
288 if (parameter_2 != ((ULONG) 0))
289 {
290
291 /* NOP code. */
292 TX_DISABLE
293 TX_RESTORE
294 }
295 }
296 }
297 }
298 }
299 #endif
300 }
301
302