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