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 
24 /**************************************************************************/
25 /*                                                                        */
26 /*  COMPONENT DEFINITION                                   RELEASE        */
27 /*                                                                        */
28 /*    tx_thread.h                                         PORTABLE C      */
29 /*                                                           6.1.9        */
30 /*  AUTHOR                                                                */
31 /*                                                                        */
32 /*    William E. Lamie, Microsoft Corporation                             */
33 /*                                                                        */
34 /*  DESCRIPTION                                                           */
35 /*                                                                        */
36 /*    This file defines the ThreadX thread control component, including   */
37 /*    data types and external references.  It is assumed that tx_api.h    */
38 /*    and tx_port.h have already been included.                           */
39 /*                                                                        */
40 /*  RELEASE HISTORY                                                       */
41 /*                                                                        */
42 /*    DATE              NAME                      DESCRIPTION             */
43 /*                                                                        */
44 /*  05-19-2020     William E. Lamie         Initial Version 6.0           */
45 /*  09-30-2020     Yuxin Zhou               Modified comment(s),          */
46 /*                                            resulting in version 6.1    */
47 /*  11-09-2020     Yuxin Zhou               Modified comment(s), and      */
48 /*                                            moved TX_THREAD_GET_SYSTEM_ */
49 /*                                            STATE to tx_api.h,          */
50 /*                                            resulting in version 6.1.2  */
51 /*  10-15-2021     Scott Larson             Modified comment(s), improved */
52 /*                                            stack check error handling, */
53 /*                                            resulting in version 6.1.9  */
54 /*                                                                        */
55 /**************************************************************************/
56 
57 #ifndef TX_THREAD_H
58 #define TX_THREAD_H
59 
60 
61 /* Define thread control specific data definitions.  */
62 
63 #define TX_THREAD_ID                            ((ULONG) 0x54485244)
64 #define TX_THREAD_PRIORITY_GROUP_MASK           ((ULONG) 0xFF)
65 #define TX_THREAD_EXECUTE_LOG_SIZE              ((UINT) 8)
66 
67 
68 /* Define the MOD32 bit set macro that is used to set/clear a priority bit within a specific
69    priority group.  */
70 
71 #if TX_MAX_PRIORITIES > 32
72 #define MAP_INDEX                               (map_index)
73 #ifndef TX_MOD32_BIT_SET
74 #define TX_MOD32_BIT_SET(a,b)                   (b) = (((ULONG) 1) << ((a)%((UINT)32)));
75 #endif
76 #else
77 #define MAP_INDEX                               (0)
78 #ifndef TX_MOD32_BIT_SET
79 #define TX_MOD32_BIT_SET(a,b)                   (b) = (((ULONG) 1) << ((a)));
80 #endif
81 #endif
82 
83 
84 /* Define the DIV32 bit set macro that is used to set/clear a priority group bit and is
85    only necessary when using priorities greater than 32.  */
86 
87 #if TX_MAX_PRIORITIES > 32
88 #ifndef TX_DIV32_BIT_SET
89 #define TX_DIV32_BIT_SET(a,b)                   (b) = (((ULONG) 1) << ((a)/((UINT) 32)));
90 #endif
91 #endif
92 
93 
94 /* Define state change macro that can be used by run-mode debug agents to keep track of thread
95    state changes. By default, it is mapped to white space.  */
96 
97 #ifndef TX_THREAD_STATE_CHANGE
98 #define TX_THREAD_STATE_CHANGE(a, b)
99 #endif
100 
101 
102 /* Define the macro to get the current thread pointer. This is particularly useful in SMP
103    versions of ThreadX to add additional processing.  The default implementation is to simply
104    access the global current thread pointer directly.  */
105 
106 #ifndef TX_THREAD_GET_CURRENT
107 #define TX_THREAD_GET_CURRENT(a)            (a) =  _tx_thread_current_ptr;
108 #endif
109 
110 
111 /* Define the macro to set the current thread pointer. This is particularly useful in SMP
112    versions of ThreadX to add additional processing.  The default implementation is to simply
113    access the global current thread pointer directly.  */
114 
115 #ifndef TX_THREAD_SET_CURRENT
116 #define TX_THREAD_SET_CURRENT(a)            _tx_thread_current_ptr =  (a);
117 #endif
118 
119 
120 
121 /* Define the get system state macro. By default, it simply maps to the variable _tx_thread_system_state.  */
122 /* This symbol is moved to tx_api.h. Therefore removed from this file.
123 #ifndef TX_THREAD_GET_SYSTEM_STATE
124 #define TX_THREAD_GET_SYSTEM_STATE()        _tx_thread_system_state
125 #endif
126 */
127 
128 /* Define the check for whether or not to call the _tx_thread_system_return function.  A non-zero value
129    indicates that _tx_thread_system_return should not be called.  */
130 
131 #ifndef TX_THREAD_SYSTEM_RETURN_CHECK
132 #define TX_THREAD_SYSTEM_RETURN_CHECK(c)    (c) = (ULONG) _tx_thread_preempt_disable; (c) = (c) | TX_THREAD_GET_SYSTEM_STATE();
133 #endif
134 
135 
136 /* Define the timeout setup macro used in _tx_thread_create.  */
137 
138 #ifndef TX_THREAD_CREATE_TIMEOUT_SETUP
139 #define TX_THREAD_CREATE_TIMEOUT_SETUP(t)    (t) -> tx_thread_timer.tx_timer_internal_timeout_function =  &(_tx_thread_timeout);                \
140                                              (t) -> tx_thread_timer.tx_timer_internal_timeout_param =     TX_POINTER_TO_ULONG_CONVERT((t));
141 #endif
142 
143 
144 /* Define the thread timeout pointer setup macro used in _tx_thread_timeout.  */
145 
146 #ifndef TX_THREAD_TIMEOUT_POINTER_SETUP
147 #define TX_THREAD_TIMEOUT_POINTER_SETUP(t)   (t) =  TX_ULONG_TO_THREAD_POINTER_CONVERT(timeout_input);
148 #endif
149 
150 
151 /* Define the lowest bit set macro. Note, that this may be overridden
152    by a port specific definition if there is supporting assembly language
153    instructions in the architecture.  */
154 
155 #ifndef TX_LOWEST_SET_BIT_CALCULATE
156 #define TX_LOWEST_SET_BIT_CALCULATE(m, b)       \
157     (b) =  ((ULONG) 0);                         \
158     (m) =  (m) & ((~(m)) + ((ULONG) 1));        \
159     if ((m) < ((ULONG) 0x10))                   \
160     {                                           \
161         if ((m) >= ((ULONG) 4))                 \
162         {                                       \
163             (m) = (m) >> ((ULONG) 2);           \
164             (b) = (b) + ((ULONG) 2);            \
165         }                                       \
166         (b) = (b) + ((m) >> ((ULONG) 1));       \
167     }                                           \
168     else if ((m) < ((ULONG) 0x100))             \
169     {                                           \
170         (m) = (m) >> ((ULONG) 4);               \
171         (b) = (b) + ((ULONG) 4);                \
172         if ((m) >= ((ULONG) 4))                 \
173         {                                       \
174             (m) = (m) >> ((ULONG) 2);           \
175             (b) = (b) + ((ULONG) 2);            \
176         }                                       \
177         (b) = (b) + ((m) >> ((ULONG) 1));       \
178     }                                           \
179     else if ((m) < ((ULONG) 0x10000))           \
180     {                                           \
181         (m) = (m) >> ((ULONG) 8);               \
182         (b) = (b) + ((ULONG) 8);                \
183         if ((m) >= ((ULONG) 0x10))              \
184         {                                       \
185             (m) = (m) >> ((ULONG) 4);           \
186             (b) = (b) + ((ULONG) 4);            \
187         }                                       \
188         if ((m) >= ((ULONG) 4))                 \
189         {                                       \
190             (m) = (m) >> ((ULONG) 2);           \
191             (b) = (b) + ((ULONG) 2);            \
192         }                                       \
193         (b) = (b) + ((m) >> ((ULONG) 1));       \
194     }                                           \
195     else                                        \
196     {                                           \
197         (m) = (m) >> ((ULONG) 16);              \
198         (b) = (b) + ((ULONG) 16);               \
199         if ((m) >= ((ULONG) 0x100))             \
200         {                                       \
201             (m) = (m) >> ((ULONG) 8);           \
202             (b) = (b) + ((ULONG) 8);            \
203         }                                       \
204         if ((m) >= ((ULONG) 16))                \
205         {                                       \
206             (m) = (m) >> ((ULONG) 4);           \
207             (b) = (b) + ((ULONG) 4);            \
208         }                                       \
209         if ((m) >= ((ULONG) 4))                 \
210         {                                       \
211             (m) = (m) >> ((ULONG) 2);           \
212             (b) = (b) + ((ULONG) 2);            \
213         }                                       \
214         (b) = (b) + ((m) >> ((ULONG) 1));       \
215     }
216 #endif
217 
218 
219 /* Define the default thread stack checking. This can be overridden by
220    a particular port, which is necessary if the stack growth is from
221    low address to high address (the default logic is for stacks that
222    grow from high address to low address.  */
223 
224 #ifndef TX_THREAD_STACK_CHECK
225 #define TX_THREAD_STACK_CHECK(thread_ptr)                                                                                       \
226     {                                                                                                                           \
227     TX_INTERRUPT_SAVE_AREA                                                                                                      \
228         TX_DISABLE                                                                                                              \
229         if (((thread_ptr)) && ((thread_ptr) -> tx_thread_id == TX_THREAD_ID))                                                   \
230         {                                                                                                                       \
231             if (((ULONG *) (thread_ptr) -> tx_thread_stack_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr))      \
232             {                                                                                                                   \
233                 (thread_ptr) -> tx_thread_stack_highest_ptr =  (thread_ptr) -> tx_thread_stack_ptr;                             \
234             }                                                                                                                   \
235             if ((*((ULONG *) (thread_ptr) -> tx_thread_stack_start) != TX_STACK_FILL) ||                                        \
236                 (*((ULONG *) (((UCHAR *) (thread_ptr) -> tx_thread_stack_end) + 1)) != TX_STACK_FILL) ||                        \
237                 (((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) < ((ULONG *) (thread_ptr) -> tx_thread_stack_start)))  \
238             {                                                                                                                   \
239                 TX_RESTORE                                                                                                      \
240                 _tx_thread_stack_error_handler((thread_ptr));                                                                   \
241                 TX_DISABLE                                                                                                      \
242             }                                                                                                                   \
243             if (*(((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) - 1) != TX_STACK_FILL)                                \
244             {                                                                                                                   \
245                 TX_RESTORE                                                                                                      \
246                 _tx_thread_stack_analyze((thread_ptr));                                                                         \
247                 TX_DISABLE                                                                                                      \
248             }                                                                                                                   \
249         }                                                                                                                       \
250         TX_RESTORE                                                                                                              \
251     }
252 #endif
253 
254 
255 /* Define default post thread delete macro to whitespace, if it hasn't been defined previously (typically in tx_port.h).  */
256 
257 #ifndef TX_THREAD_DELETE_PORT_COMPLETION
258 #define TX_THREAD_DELETE_PORT_COMPLETION(t)
259 #endif
260 
261 
262 /* Define default post thread reset macro to whitespace, if it hasn't been defined previously (typically in tx_port.h).  */
263 
264 #ifndef TX_THREAD_RESET_PORT_COMPLETION
265 #define TX_THREAD_RESET_PORT_COMPLETION(t)
266 #endif
267 
268 
269 /* Define the thread create internal extension macro to whitespace, if it hasn't been defined previously (typically in tx_port.h).  */
270 
271 #ifndef TX_THREAD_CREATE_INTERNAL_EXTENSION
272 #define TX_THREAD_CREATE_INTERNAL_EXTENSION(t)
273 #endif
274 
275 
276 /* Define internal thread control function prototypes.  */
277 
278 VOID        _tx_thread_initialize(VOID);
279 VOID        _tx_thread_schedule(VOID);
280 VOID        _tx_thread_shell_entry(VOID);
281 VOID        _tx_thread_stack_analyze(TX_THREAD *thread_ptr);
282 VOID        _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID));
283 VOID        _tx_thread_stack_error(TX_THREAD *thread_ptr);
284 VOID        _tx_thread_stack_error_handler(TX_THREAD *thread_ptr);
285 VOID        _tx_thread_system_preempt_check(VOID);
286 VOID        _tx_thread_system_resume(TX_THREAD *thread_ptr);
287 VOID        _tx_thread_system_ni_resume(TX_THREAD *thread_ptr);
288 VOID        _tx_thread_system_return(VOID);
289 VOID        _tx_thread_system_suspend(TX_THREAD *thread_ptr);
290 VOID        _tx_thread_system_ni_suspend(TX_THREAD *thread_ptr, ULONG wait_option);
291 VOID        _tx_thread_time_slice(VOID);
292 VOID        _tx_thread_timeout(ULONG timeout_input);
293 
294 
295 /* Thread control component data declarations follow.  */
296 
297 /* Determine if the initialization function of this component is including
298    this file.  If so, make the data definitions really happen.  Otherwise,
299    make them extern so other functions in the component can access them.  */
300 
301 #define THREAD_DECLARE extern
302 
303 
304 /* Define the pointer that contains the system stack pointer.  This is
305    utilized when control returns from a thread to the system to reset the
306    current stack.  This is setup in the low-level initialization function. */
307 
308 THREAD_DECLARE  VOID *          _tx_thread_system_stack_ptr;
309 
310 
311 /* Define the current thread pointer.  This variable points to the currently
312    executing thread.  If this variable is NULL, no thread is executing.  */
313 
314 THREAD_DECLARE  TX_THREAD *     _tx_thread_current_ptr;
315 
316 
317 /* Define the variable that holds the next thread to execute.  It is important
318    to remember that this is not necessarily equal to the current thread
319    pointer.  */
320 
321 THREAD_DECLARE  TX_THREAD *     _tx_thread_execute_ptr;
322 
323 
324 /* Define the head pointer of the created thread list.  */
325 
326 THREAD_DECLARE  TX_THREAD *     _tx_thread_created_ptr;
327 
328 
329 /* Define the variable that holds the number of created threads. */
330 
331 THREAD_DECLARE  ULONG           _tx_thread_created_count;
332 
333 
334 /* Define the current state variable.  When this value is 0, a thread
335    is executing or the system is idle.  Other values indicate that
336    interrupt or initialization processing is active.  This variable is
337    initialized to TX_INITIALIZE_IN_PROGRESS to indicate initialization is
338    active.  */
339 
340 THREAD_DECLARE  volatile ULONG  _tx_thread_system_state;
341 
342 
343 /* Define the 32-bit priority bit-maps. There is one priority bit map for each
344    32 priority levels supported. If only 32 priorities are supported there is
345    only one bit map. Each bit within a priority bit map represents that one
346    or more threads at the associated thread priority are ready.  */
347 
348 THREAD_DECLARE  ULONG           _tx_thread_priority_maps[TX_MAX_PRIORITIES/32];
349 
350 
351 /* Define the priority map active bit map that specifies which of the previously
352    defined priority maps have something set. This is only necessary if more than
353    32 priorities are supported.  */
354 
355 #if TX_MAX_PRIORITIES > 32
356 THREAD_DECLARE  ULONG           _tx_thread_priority_map_active;
357 #endif
358 
359 
360 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD
361 
362 /* Define the 32-bit preempt priority bit maps.  There is one preempt bit map
363    for each 32 priority levels supported. If only 32 priorities are supported
364    there is only one bit map. Each set set bit corresponds to a preempted priority
365    level that had preemption-threshold active to protect against preemption of a
366    range of relatively higher priority threads.  */
367 
368 THREAD_DECLARE  ULONG           _tx_thread_preempted_maps[TX_MAX_PRIORITIES/32];
369 
370 
371 /* Define the preempt map active bit map that specifies which of the previously
372    defined preempt maps have something set. This is only necessary if more than
373    32 priorities are supported.  */
374 
375 #if TX_MAX_PRIORITIES > 32
376 THREAD_DECLARE  ULONG           _tx_thread_preempted_map_active;
377 #endif
378 #endif
379 
380 /* Define the variable that holds the highest priority group ready for
381    execution.  It is important to note that this is not necessarily the same
382    as the priority of the thread pointed to by _tx_execute_thread.  */
383 
384 THREAD_DECLARE  UINT            _tx_thread_highest_priority;
385 
386 
387 /* Define the array of thread pointers.  Each entry represents the threads that
388    are ready at that priority group.  For example, index 10 in this array
389    represents the first thread ready at priority 10.  If this entry is NULL,
390    no threads are ready at that priority.  */
391 
392 THREAD_DECLARE  TX_THREAD *     _tx_thread_priority_list[TX_MAX_PRIORITIES];
393 
394 
395 /* Define the global preempt disable variable.  If this is non-zero, preemption is
396    disabled.  It is used internally by ThreadX to prevent preemption of a thread in
397    the middle of a service that is resuming or suspending another thread.  */
398 
399 THREAD_DECLARE  volatile UINT   _tx_thread_preempt_disable;
400 
401 
402 /* Define the global function pointer for mutex cleanup on thread completion or
403    termination. This pointer is setup during mutex initialization.  */
404 
405 THREAD_DECLARE  VOID            (*_tx_thread_mutex_release)(TX_THREAD *thread_ptr);
406 
407 
408 /* Define the global build options variable.  This contains a bit map representing
409    how the ThreadX library was built. The following are the bit field definitions:
410 
411                     Bit(s)                   Meaning
412 
413                     31                  TX_NOT_INTERRUPTABLE defined
414                     30                  TX_INLINE_THREAD_RESUME_SUSPEND define
415                     29-24               Priority groups 1  -> 32 priorities
416                                                         2  -> 64 priorities
417                                                         3  -> 96 priorities
418 
419                                                         ...
420 
421                                                         32 -> 1024 priorities
422                     23                  TX_TIMER_PROCESS_IN_ISR defined
423                     22                  TX_REACTIVATE_INLINE defined
424                     21                  TX_DISABLE_STACK_FILLING defined
425                     20                  TX_ENABLE_STACK_CHECKING defined
426                     19                  TX_DISABLE_PREEMPTION_THRESHOLD defined
427                     18                  TX_DISABLE_REDUNDANT_CLEARING defined
428                     17                  TX_DISABLE_NOTIFY_CALLBACKS defined
429                     16                  TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO defined
430                     15                  TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO defined
431                     14                  TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO defined
432                     13                  TX_MUTEX_ENABLE_PERFORMANCE_INFO defined
433                     12                  TX_QUEUE_ENABLE_PERFORMANCE_INFO defined
434                     11                  TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO defined
435                     10                  TX_THREAD_ENABLE_PERFORMANCE_INFO defined
436                     9                   TX_TIMER_ENABLE_PERFORMANCE_INFO defined
437                     8                   TX_ENABLE_EVENT_TRACE defined
438                     7                   TX_ENABLE_EXECUTION_CHANGE_NOTIFY defined
439                     6-0                 Port Specific   */
440 
441 THREAD_DECLARE  ULONG           _tx_build_options;
442 
443 
444 #if defined(TX_ENABLE_STACK_CHECKING) || defined(TX_PORT_THREAD_STACK_ERROR_HANDLING)
445 
446 /* Define the global function pointer for stack error handling. If a stack error is
447    detected and the application has registered a stack error handler, it will be
448    called via this function pointer.  */
449 
450 THREAD_DECLARE  VOID            (*_tx_thread_application_stack_error_handler)(TX_THREAD *thread_ptr);
451 
452 #endif
453 
454 #ifdef TX_THREAD_ENABLE_PERFORMANCE_INFO
455 
456 /* Define the total number of thread resumptions. Each time a thread enters the
457    ready state this variable is incremented.  */
458 
459 THREAD_DECLARE  ULONG           _tx_thread_performance_resume_count;
460 
461 
462 /* Define the total number of thread suspensions. Each time a thread enters a
463    suspended state this variable is incremented.  */
464 
465 THREAD_DECLARE  ULONG           _tx_thread_performance_suspend_count;
466 
467 
468 /* Define the total number of solicited thread preemptions. Each time a thread is
469    preempted by directly calling a ThreadX service, this variable is incremented.  */
470 
471 THREAD_DECLARE  ULONG           _tx_thread_performance_solicited_preemption_count;
472 
473 
474 /* Define the total number of interrupt thread preemptions. Each time a thread is
475    preempted as a result of an ISR calling a ThreadX service, this variable is
476    incremented.  */
477 
478 THREAD_DECLARE  ULONG           _tx_thread_performance_interrupt_preemption_count;
479 
480 
481 /* Define the total number of priority inversions. Each time a thread is blocked by
482    a mutex owned by a lower-priority thread, this variable is incremented.  */
483 
484 THREAD_DECLARE  ULONG           _tx_thread_performance_priority_inversion_count;
485 
486 
487 /* Define the total number of time-slices.  Each time a time-slice operation is
488    actually performed (another thread is setup for running) this variable is
489    incremented.  */
490 
491 THREAD_DECLARE  ULONG           _tx_thread_performance_time_slice_count;
492 
493 
494 /* Define the total number of thread relinquish operations.  Each time a thread
495    relinquish operation is actually performed (another thread is setup for running)
496    this variable is incremented.  */
497 
498 THREAD_DECLARE  ULONG           _tx_thread_performance_relinquish_count;
499 
500 
501 /* Define the total number of thread timeouts. Each time a thread has a
502    timeout this variable is incremented.  */
503 
504 THREAD_DECLARE  ULONG           _tx_thread_performance_timeout_count;
505 
506 
507 /* Define the total number of thread wait aborts. Each time a thread's suspension
508    is lifted by the tx_thread_wait_abort call this variable is incremented.  */
509 
510 THREAD_DECLARE  ULONG           _tx_thread_performance_wait_abort_count;
511 
512 
513 /* Define the total number of idle system thread returns. Each time a thread returns to
514    an idle system (no other thread is ready to run) this variable is incremented.  */
515 
516 THREAD_DECLARE  ULONG           _tx_thread_performance_idle_return_count;
517 
518 
519 /* Define the total number of non-idle system thread returns. Each time a thread returns to
520    a non-idle system (another thread is ready to run) this variable is incremented.  */
521 
522 THREAD_DECLARE  ULONG           _tx_thread_performance_non_idle_return_count;
523 
524 
525 /* Define the last TX_THREAD_EXECUTE_LOG_SIZE threads scheduled in ThreadX. This
526    is a circular list, where the index points to the oldest entry.  */
527 
528 THREAD_DECLARE  ULONG           _tx_thread_performance__execute_log_index;
529 THREAD_DECLARE  TX_THREAD *     _tx_thread_performance_execute_log[TX_THREAD_EXECUTE_LOG_SIZE];
530 
531 #endif
532 
533 #endif
534 
535