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