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