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