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