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