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