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 /**   Thread                                                              */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 
24 
25 #ifndef TX_MISRA_ENABLE
26 #define TX_THREAD_INIT
27 #endif
28 
29 
30 /* Include necessary system files.  */
31 
32 #include "tx_api.h"
33 #include "tx_initialize.h"
34 #include "tx_thread.h"
35 
36 
37 /* Define the pointer that contains the system stack pointer.  This is
38    utilized when control returns from a thread to the system to reset the
39    current stack.  This is setup in the low-level initialization function. */
40 
41 VOID *          _tx_thread_system_stack_ptr;
42 
43 
44 /* Define the current thread pointer.  This variable points to the currently
45    executing thread.  If this variable is NULL, no thread is executing.  */
46 
47 TX_THREAD *     _tx_thread_current_ptr;
48 
49 
50 /* Define the variable that holds the next thread to execute.  It is important
51    to remember that this is not necessarily equal to the current thread
52    pointer.  */
53 
54 TX_THREAD *     _tx_thread_execute_ptr;
55 
56 
57 /* Define the head pointer of the created thread list.  */
58 
59 TX_THREAD *     _tx_thread_created_ptr;
60 
61 
62 /* Define the variable that holds the number of created threads. */
63 
64 ULONG           _tx_thread_created_count;
65 
66 
67 /* Define the current state variable.  When this value is 0, a thread
68    is executing or the system is idle.  Other values indicate that
69    interrupt or initialization processing is active.  This variable is
70    initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is
71    active.  */
72 
73 volatile ULONG  _tx_thread_system_state =  TX_INITIALIZE_IN_PROGRESS;
74 
75 
76 /* Define the 32-bit priority bit-maps. There is one priority bit map for each
77    32 priority levels supported. If only 32 priorities are supported there is
78    only one bit map. Each bit within a priority bit map represents that one
79    or more threads at the associated thread priority are ready.  */
80 
81 ULONG           _tx_thread_priority_maps[TX_MAX_PRIORITIES/32];
82 
83 
84 /* Define the priority map active bit map that specifies which of the previously
85    defined priority maps have something set. This is only necessary if more than
86    32 priorities are supported.  */
87 
88 #if TX_MAX_PRIORITIES > 32
89 ULONG           _tx_thread_priority_map_active;
90 #endif
91 
92 
93 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
94 
95 /* Define the 32-bit preempt priority bit maps.  There is one preempt bit map
96    for each 32 priority levels supported. If only 32 priorities are supported
97    there is only one bit map. Each set set bit corresponds to a preempted priority
98    level that had preemption-threshold active to protect against preemption of a
99    range of relatively higher priority threads.  */
100 
101 ULONG           _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];
102 
103 
104 /* Define the preempt map active bit map that specifies which of the previously
105    defined preempt maps have something set. This is only necessary if more than
106    32 priorities are supported.  */
107 
108 #if TX_MAX_PRIORITIES > 32
109 ULONG           _tx_thread_preempted_map_active;
110 #endif
111 #endif
112 
113 /* Define the variable that holds the highest priority group ready for
114    execution.  It is important to note that this is not necessarily the same
115    as the priority of the thread pointed to by _tx_execute_thread.  */
116 
117 UINT            _tx_thread_highest_priority;
118 
119 
120 /* Define the array of thread pointers.  Each entry represents the threads that
121    are ready at that priority group.  For example, index 10 in this array
122    represents the first thread ready at priority 10.  If this entry is NULL,
123    no threads are ready at that priority.  */
124 
125 TX_THREAD *     _tx_thread_priority_list[TX_MAX_PRIORITIES];
126 
127 
128 /* Define the global preempt disable variable.  If this is non-zero, preemption is
129    disabled.  It is used internally by ThreadX to prevent preemption of a thread in
130    the middle of a service that is resuming or suspending another thread.  */
131 
132 volatile UINT   _tx_thread_preempt_disable;
133 
134 
135 /* Define the global function pointer for mutex cleanup on thread completion or
136    termination. This pointer is setup during mutex initialization.  */
137 
138 VOID            (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr);
139 
140 
141 /* Define the global build options variable.  This contains a bit map representing
142    how the ThreadX library was built. The following are the bit field definitions:
143 
144                     Bit(s)                   Meaning
145 
146                     31                  TX_NOT_INTERRUPTABLE defined
147                     30                  TX_INLINE_THREAD_RESUME_SUSPEND define
148                     29-24               Priority groups 1  -> 32 priorities
149                                                         2  -> 64 priorities
150                                                         3  -> 96 priorities
151 
152                                                         ...
153 
154                                                         32 -> 1024 priorities
155                     23                  TX_TIMER_PROCESS_IN_ISR defined
156                     22                  TX_REACTIVATE_INLINE defined
157                     21                  TX_DISABLE_STACK_FILLING defined
158                     20                  TX_ENABLE_STACK_CHECKING defined
159                     19                  TX_DISABLE_PREEMPTION_THRESHOLD defined
160                     18                  TX_DISABLE_REDUNDANT_CLEARING defined
161                     17                  TX_DISABLE_NOTIFY_CALLBACKS defined
162                     16                  TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined
163                     15                  TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined
164                     14                  TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined
165                     13                  TX_MUTEX_ENABLE_PERFORMANCE_INFO defined
166                     12                  TX_QUEUE_ENABLE_PERFORMANCE_INFO defined
167                     11                  TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined
168                     10                  TX_THREAD_ENABLE_PERFORMANCE_INFO defined
169                     9                   TX_TIMER_ENABLE_PERFORMANCE_INFO defined
170                     8                   TX_ENABLE_EVENT_TRACE defined
171                     7                   TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined
172                     6-0                 Port Specific   */
173 
174 ULONG           _tx_build_options;
175 
176 
177 #if defined(TX_ENABLE_STACK_CHECKING) || defined(TX_PORT_THREAD_STACK_ERROR_HANDLING)
178 
179 /* Define the global function pointer for stack error handling. If a stack error is
180    detected and the application has registered a stack error handler, it will be
181    called via this function pointer.  */
182 
183 VOID            (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr);
184 
185 #endif
186 
187 #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
188 
189 /* Define the total number of thread resumptions. Each time a thread enters the
190    ready state this variable is incremented.  */
191 
192 ULONG           _tx_thread_performance_resume_count;
193 
194 
195 /* Define the total number of thread suspensions. Each time a thread enters a
196    suspended state this variable is incremented.  */
197 
198 ULONG           _tx_thread_performance_suspend_count;
199 
200 
201 /* Define the total number of solicited thread preemptions. Each time a thread is
202    preempted by directly calling a ThreadX service, this variable is incremented.  */
203 
204 ULONG           _tx_thread_performance_solicited_preemption_count;
205 
206 
207 /* Define the total number of interrupt thread preemptions. Each time a thread is
208    preempted as a result of an ISR calling a ThreadX service, this variable is
209    incremented.  */
210 
211 ULONG           _tx_thread_performance_interrupt_preemption_count;
212 
213 
214 /* Define the total number of priority inversions. Each time a thread is blocked by
215    a mutex owned by a lower-priority thread, this variable is incremented.  */
216 
217 ULONG           _tx_thread_performance_priority_inversion_count;
218 
219 
220 /* Define the total number of time-slices.  Each time a time-slice operation is
221    actually performed (another thread is setup for running) this variable is
222    incremented.  */
223 
224 ULONG           _tx_thread_performance_time_slice_count;
225 
226 
227 /* Define the total number of thread relinquish operations.  Each time a thread
228    relinquish operation is actually performed (another thread is setup for running)
229    this variable is incremented.  */
230 
231 ULONG           _tx_thread_performance_relinquish_count;
232 
233 
234 /* Define the total number of thread timeouts. Each time a thread has a
235    timeout this variable is incremented.  */
236 
237 ULONG           _tx_thread_performance_timeout_count;
238 
239 
240 /* Define the total number of thread wait aborts. Each time a thread's suspension
241    is lifted by the tx_thread_wait_abort call this variable is incremented.  */
242 
243 ULONG           _tx_thread_performance_wait_abort_count;
244 
245 
246 /* Define the total number of idle system thread returns. Each time a thread returns to
247    an idle system (no other thread is ready to run) this variable is incremented.  */
248 
249 ULONG           _tx_thread_performance_idle_return_count;
250 
251 
252 /* Define the total number of non-idle system thread returns. Each time a thread returns to
253    a non-idle system (another thread is ready to run) this variable is incremented.  */
254 
255 ULONG           _tx_thread_performance_non_idle_return_count;
256 
257 
258 /* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This
259    is a circular list, where the index points to the oldest entry.  */
260 
261 ULONG           _tx_thread_performance__execute_log_index;
262 TX_THREAD *     _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE];
263 #endif
264 
265 
266 /* Define special string.  */
267 
268 #ifndef TX_MISRA_ENABLE
269 const CHAR _tx_thread_special_string[] =
270   "G-ML-EL-ML-BL-DL-BL-GB-GL-M-D-DL-GZ-KH-EL-CM-NH-HA-GF-DD-JC-YZ-CT-AT-DW-USA-CA-SD-SDSU";
271 #endif
272 
273 
274 /**************************************************************************/
275 /*                                                                        */
276 /*  FUNCTION                                               RELEASE        */
277 /*                                                                        */
278 /*    _tx_thread_initialize                               PORTABLE C      */
279 /*                                                           6.1.9        */
280 /*  AUTHOR                                                                */
281 /*                                                                        */
282 /*    William E. Lamie, Microsoft Corporation                             */
283 /*                                                                        */
284 /*  DESCRIPTION                                                           */
285 /*                                                                        */
286 /*    This function initializes the various control data structures for   */
287 /*    the thread control component.                                       */
288 /*                                                                        */
289 /*  INPUT                                                                 */
290 /*                                                                        */
291 /*    None                                                                */
292 /*                                                                        */
293 /*  OUTPUT                                                                */
294 /*                                                                        */
295 /*    None                                                                */
296 /*                                                                        */
297 /*  CALLS                                                                 */
298 /*                                                                        */
299 /*    None                                                                */
300 /*                                                                        */
301 /*  CALLED BY                                                             */
302 /*                                                                        */
303 /*    _tx_initialize_high_level         High level initialization         */
304 /*                                                                        */
305 /*  RELEASE HISTORY                                                       */
306 /*                                                                        */
307 /*    DATE              NAME                      DESCRIPTION             */
308 /*                                                                        */
309 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
310 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
311 /*                                            resulting in version 6.1    */
312 /*  06-02-2021     Yuxin Zhou               Modified comment(s), added    */
313 /*                                            Execution Profile support,  */
314 /*                                            resulting in version 6.1.7  */
315 /*  10-15-2021     Yuxin Zhou               Modified comment(s), improved */
316 /*                                            stack check error handling, */
317 /*                                            resulting in version 6.1.9  */
318 /*                                                                        */
319 /**************************************************************************/
_tx_thread_initialize(VOID)320 VOID  _tx_thread_initialize(VOID)
321 {
322 
323     /* Note: the system stack pointer and the system state variables are
324        initialized by the low and high-level initialization functions,
325        respectively.  */
326 
327 #ifndef TX_DISABLE_REDUNDANT_CLEARING
328 
329     /* Set current thread pointer to NULL.  */
330     TX_THREAD_SET_CURRENT(TX_NULL)
331 
332     /* Initialize the execute thread pointer to NULL.  */
333     _tx_thread_execute_ptr =  TX_NULL;
334 
335     /* Initialize the priority information.  */
336     TX_MEMSET(&_tx_thread_priority_maps[0], 0, (sizeof(_tx_thread_priority_maps)));
337 
338 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
339     TX_MEMSET(&_tx_thread_preempted_maps[0], 0, (sizeof(_tx_thread_preempted_maps)));
340 #endif
341 #endif
342 
343     /* Setup the highest priority variable to the max, indicating no thread is currently
344        ready.  */
345     _tx_thread_highest_priority =  ((UINT) TX_MAX_PRIORITIES);
346 
347 
348 #ifndef TX_DISABLE_REDUNDANT_CLEARING
349 
350     /* Initialize the array of priority head pointers.  */
351     TX_MEMSET(&_tx_thread_priority_list[0], 0, (sizeof(_tx_thread_priority_list)));
352 
353     /* Initialize the head pointer of the created threads list and the
354        number of threads created.  */
355     _tx_thread_created_ptr =        TX_NULL;
356     _tx_thread_created_count =      TX_EMPTY;
357 
358     /* Clear the global preempt disable variable.  */
359     _tx_thread_preempt_disable =    ((UINT) 0);
360 
361     /* Initialize the thread mutex release function pointer.  */
362     _tx_thread_mutex_release =      TX_NULL;
363 
364 #ifdef TX_ENABLE_STACK_CHECKING
365 
366     /* Clear application registered stack error handler.  */
367     _tx_thread_application_stack_error_handler =  TX_NULL;
368 #endif
369 
370 #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
371 
372     /* Clear performance counters.  */
373     _tx_thread_performance_resume_count =                ((ULONG) 0);
374     _tx_thread_performance_suspend_count =               ((ULONG) 0);
375     _tx_thread_performance_solicited_preemption_count =  ((ULONG) 0);
376     _tx_thread_performance_interrupt_preemption_count =  ((ULONG) 0);
377     _tx_thread_performance_priority_inversion_count =    ((ULONG) 0);
378     _tx_thread_performance_time_slice_count =            ((ULONG) 0);
379     _tx_thread_performance_relinquish_count =            ((ULONG) 0);
380     _tx_thread_performance_timeout_count =               ((ULONG) 0);
381     _tx_thread_performance_wait_abort_count =            ((ULONG) 0);
382     _tx_thread_performance_idle_return_count =           ((ULONG) 0);
383     _tx_thread_performance_non_idle_return_count =       ((ULONG) 0);
384 
385     /* Initialize the execute thread log.  */
386     TX_MEMSET(&_tx_thread_performance_execute_log[0], 0, (sizeof(_tx_thread_performance_execute_log)));
387 #endif
388 #endif
389 
390     /* Setup the build options flag. This is used to identify how the ThreadX library was constructed.  */
391     _tx_build_options =  _tx_build_options
392                             | (((ULONG) (TX_MAX_PRIORITIES/32)) << 24)
393 #ifdef TX_NOT_INTERRUPTABLE
394                             | (((ULONG) 1) << 31)
395 #endif
396 #ifdef TX_INLINE_THREAD_RESUME_SUSPEND
397                             | (((ULONG) 1) << 30)
398 #endif
399 #ifdef TX_TIMER_PROCESS_IN_ISR
400                             | (((ULONG) 1) << 23)
401 #endif
402 #ifdef TX_REACTIVATE_INLINE
403                             | (((ULONG) 1) << 22)
404 #endif
405 #ifdef TX_DISABLE_STACK_FILLING
406                             | (((ULONG) 1) << 21)
407 #endif
408 #ifdef TX_ENABLE_STACK_CHECKING
409                             | (((ULONG) 1) << 20)
410 #endif
411 #ifdef TX_DISABLE_PREEMPTION_THRESHOLD
412                             | (((ULONG) 1) << 19)
413 #endif
414 #ifdef TX_DISABLE_REDUNDANT_CLEARING
415                             | (((ULONG) 1) << 18)
416 #endif
417 #ifdef TX_DISABLE_NOTIFY_CALLBACKS
418                             | (((ULONG) 1) << 17)
419 #endif
420 #ifdef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO
421                             | (((ULONG) 1) << 16)
422 #endif
423 #ifdef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO
424                             | (((ULONG) 1) << 15)
425 #endif
426 #ifdef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO
427                             | (((ULONG) 1) << 14)
428 #endif
429 #ifdef TX_MUTEX_ENABLE_PERFORMANCE_INFO
430                             | (((ULONG) 1) << 13)
431 #endif
432 #ifdef TX_QUEUE_ENABLE_PERFORMANCE_INFO
433                             | (((ULONG) 1) << 12)
434 #endif
435 #ifdef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO
436                             | (((ULONG) 1) << 11)
437 #endif
438 #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
439                             | (((ULONG) 1) << 10)
440 #endif
441 #ifdef TX_TIMER_ENABLE_PERFORMANCE_INFO
442                             | (((ULONG) 1) << 9)
443 #endif
444 #ifdef TX_ENABLE_EVENT_TRACE
445                             | (((ULONG) 1) << 8)
446 #endif
447 #if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)
448                             | (((ULONG) 1) << 7)
449 #endif
450 #if TX_PORT_SPECIFIC_BUILD_OPTIONS != 0
451                             | TX_PORT_SPECIFIC_BUILD_OPTIONS
452 #endif
453                             ;
454 }
455 
456