diff options
Diffstat (limited to 'utility/execution_profile_kit/smp_version')
| -rw-r--r-- | utility/execution_profile_kit/smp_version/tx_execution_profile.c | 195 | ||||
| -rw-r--r-- | utility/execution_profile_kit/smp_version/tx_execution_profile.h | 25 |
2 files changed, 108 insertions, 112 deletions
diff --git a/utility/execution_profile_kit/smp_version/tx_execution_profile.c b/utility/execution_profile_kit/smp_version/tx_execution_profile.c index 3b5c05a2..735dbf14 100644 --- a/utility/execution_profile_kit/smp_version/tx_execution_profile.c +++ b/utility/execution_profile_kit/smp_version/tx_execution_profile.c @@ -1,10 +1,11 @@ /*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors + * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. - * + * * SPDX-License-Identifier: MIT **************************************************************************/ @@ -27,44 +28,44 @@ #include "tx_api.h" #include "tx_execution_profile.h" -/* The thread execution profile kit is designed to track thread execution time - based on the hardware timer defined by TX_EXECUTION_TIME_SOURCE and - TX_EXECUTION_MAX_TIME_SOURCE below. When the thread's total time reaches +/* The thread execution profile kit is designed to track thread execution time + based on the hardware timer defined by TX_EXECUTION_TIME_SOURCE and + TX_EXECUTION_MAX_TIME_SOURCE below. When the thread's total time reaches the maximum value, it remains there until the time is reset to 0 via a call - to tx_thread_execution_time_reset. There are several assumptions to the + to tx_thread_execution_time_reset. There are several assumptions to the operation of this kit, as follows: 1. In tx_port.h replace: - - #define TX_THREAD_EXTENSION_3" - + + #define TX_THREAD_EXTENSION_3" + with: - + #define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \ - unsigned long tx_thread_execution_time_last_start; - + unsigned long tx_thread_execution_time_last_start; + Note: if 64-bit time source is present, the tx_thread_execution_time_last_start type should be unsigned long long. - 2. The TX_EXECUTION_TIME_SOURCE and TX_EXECUTION_MAX_TIME_SOURCE macros are + 2. The TX_EXECUTION_TIME_SOURCE and TX_EXECUTION_MAX_TIME_SOURCE macros are defined to utilize a local hardware time source. - + 3. ThreadX 5.4 (or later) is being used, with the assembly code enabled to call the following routines from assembly code: - + VOID _tx_execution_thread_enter(void); VOID _tx_execution_thread_exit(void); VOID _tx_execution_isr_enter(void); VOID _tx_execution_isr_exit(void); - - 4. The ThreadX library assembly code must be rebuilt with TX_ENABLE_EXECUTION_CHANGE_NOTIFY so - that these macros are expanded in the TX_THREAD structure and so the assembly code macros - are enabled to call the execution profile routines. + + 4. The ThreadX library assembly code must be rebuilt with TX_ENABLE_EXECUTION_CHANGE_NOTIFY so + that these macros are expanded in the TX_THREAD structure and so the assembly code macros + are enabled to call the execution profile routines. 5. Add tx_execution_profile.c to the application build. */ /* Externally reference several internal ThreadX variables. */ - + extern ULONG _tx_thread_system_state[TX_THREAD_SMP_MAX_CORES]; extern UINT _tx_thread_preempt_disable; extern TX_THREAD *_tx_thread_current_ptr[TX_THREAD_SMP_MAX_CORES]; @@ -83,11 +84,11 @@ EXECUTION_TIME _tx_execution_thread_time_total[TX_THREAD_SM and _tx_thread_context_restore are tracked by this utility. */ EXECUTION_TIME _tx_execution_isr_time_total[TX_THREAD_SMP_MAX_CORES]; -EXECUTION_TIME_SOURCE_TYPE _tx_execution_isr_time_last_start[TX_THREAD_SMP_MAX_CORES]; +EXECUTION_TIME_SOURCE_TYPE _tx_execution_isr_time_last_start[TX_THREAD_SMP_MAX_CORES]; /* Define the system idle time gathering information. For idle time that exceeds the range of the timer - source, another timer source may be needed. In addition, the total thread execution time added to the + source, another timer source may be needed. In addition, the total thread execution time added to the total ISR time, less the total system time is also a measure of idle time. */ EXECUTION_TIME _tx_execution_idle_time_total[TX_THREAD_SMP_MAX_CORES]; @@ -124,12 +125,6 @@ EXECUTION_TIME_SOURCE_TYPE _tx_execution_idle_time_last_start[TX_THREAD /* */ /* _tx_thread_schedule Thread scheduling */ /* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 07-29-2022 William E. Lamie Initial Version 6.1.12 */ -/* */ /**************************************************************************/ VOID _tx_execution_thread_enter(void) { @@ -155,10 +150,10 @@ UINT core; /* This thread is being scheduled. Simply setup the last start time in the thread control block. */ thread_ptr -> tx_thread_execution_time_last_start = current_time; - + /* Pickup the last idle start time. */ last_start_time = _tx_execution_idle_time_last_start[core]; - + /* Determine if idle time is being measured. */ if (last_start_time) { @@ -166,34 +161,34 @@ UINT core; /* Determine how to calculate the difference. */ if (current_time >= last_start_time) { - + /* Simply subtract. */ delta_time = (EXECUTION_TIME) (current_time - last_start_time); - } + } else { - + /* Timer wrapped, compute the delta assuming incrementing time counter. */ delta_time = (EXECUTION_TIME) (current_time + (((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) - last_start_time)); } - + /* Pickup the total time. */ total_time = _tx_execution_idle_time_total[core]; /* Now compute the new total time. */ new_total_time = total_time + delta_time; - + /* Determine if a rollover on the total time is present. */ if (new_total_time < total_time) { - + /* Rollover. Set the total time to max value. */ new_total_time = (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE; } - + /* Now store back the total idle time. */ - _tx_execution_idle_time_total[core] = new_total_time; - + _tx_execution_idle_time_total[core] = new_total_time; + /* Disable the idle time measurement. */ _tx_execution_idle_time_last_start[core] = 0; } @@ -258,7 +253,7 @@ UINT core; /* Determine if there is a thread. */ if (thread_ptr) { - + /* Pickup the current time. */ current_time = TX_EXECUTION_TIME_SOURCE; @@ -271,17 +266,17 @@ UINT core; /* Clear the last start time. */ thread_ptr -> tx_thread_execution_time_last_start = 0; - + /* Determine how to calculate the difference. */ if (current_time >= last_start_time) { - + /* Simply subtract. */ delta_time = (EXECUTION_TIME) (current_time - last_start_time); - } + } else { - + /* Timer wrapped, compute the delta assuming incrementing time counter. */ delta_time = (EXECUTION_TIME) (current_time + (((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) - last_start_time)); } @@ -291,37 +286,37 @@ UINT core; /* Now compute the new total time. */ new_total_time = total_time + delta_time; - + /* Determine if a rollover on the total time is present. */ if (new_total_time < total_time) { - + /* Rollover. Set the total time to max value. */ new_total_time = (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE; } - + /* Store back the new total time. */ thread_ptr -> tx_thread_execution_time_total = new_total_time; - + /* Now accumulate this thread's execution time into the total thread execution time. */ new_total_time = _tx_execution_thread_time_total[core] + delta_time; - + /* Determine if a rollover on the total time is present. */ if (new_total_time < _tx_execution_thread_time_total[core]) { - + /* Rollover. Set the total time to max value. */ new_total_time = (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE; - } + } /* Store back the new total time. */ _tx_execution_thread_time_total[core] = new_total_time; } - + /* Is the system now idle? */ if (_tx_thread_execute_ptr[core] == TX_NULL) { - + /* Yes, idle system. Pickup the start of idle time. */ _tx_execution_idle_time_last_start[core] = TX_EXECUTION_TIME_SOURCE; } @@ -381,7 +376,7 @@ UINT core; /* Pickup the core index. */ core = TX_SMP_CORE_ID; - /* Determine if this is the first interrupt. Nested interrupts are all treated as + /* Determine if this is the first interrupt. Nested interrupts are all treated as general interrupt processing. */ if (_tx_thread_system_state[core] == 1) { @@ -394,7 +389,7 @@ UINT core; /* Determine if a thread was interrupted. */ if (thread_ptr) { - + /* Pickup the last start time. */ last_start_time = thread_ptr -> tx_thread_execution_time_last_start; @@ -404,17 +399,17 @@ UINT core; /* Clear the last start time. */ thread_ptr -> tx_thread_execution_time_last_start = 0; - + /* Determine how to calculate the difference. */ if (current_time >= last_start_time) { - + /* Simply subtract. */ delta_time = (EXECUTION_TIME) (current_time - last_start_time); - } + } else { - + /* Timer wrapped, compute the delta assuming incrementing time counter. */ delta_time = (EXECUTION_TIME) (current_time + (((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) - last_start_time)); } @@ -424,72 +419,72 @@ UINT core; /* Now compute the new total time. */ new_total_time = total_time + delta_time; - + /* Determine if a rollover on the total time is present. */ if (new_total_time < total_time) { - + /* Rollover. Set the total time to max value. */ new_total_time = (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE; } - + /* Store back the new total time. */ thread_ptr -> tx_thread_execution_time_total = new_total_time; /* Now accumulate this thread's execution time into the total thread execution time. */ new_total_time = _tx_execution_thread_time_total[core] + delta_time; - + /* Determine if a rollover on the total time is present. */ if (new_total_time < _tx_execution_thread_time_total[core]) { - + /* Rollover. Set the total time to max value. */ new_total_time = (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE; - } + } /* Store back the new total time. */ _tx_execution_thread_time_total[core] = new_total_time; } } - + /* Has idle time started? */ else if (_tx_execution_idle_time_last_start[core]) { - + /* Pickup the last idle start time. */ last_start_time = _tx_execution_idle_time_last_start[core]; - + /* Determine how to calculate the difference. */ if (current_time >= last_start_time) { - + /* Simply subtract. */ delta_time = (EXECUTION_TIME) (current_time - last_start_time); - } + } else { - + /* Timer wrapped, compute the delta assuming incrementing time counter. */ delta_time = (EXECUTION_TIME) (current_time + (((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) - last_start_time)); } - + /* Pickup the total time. */ total_time = _tx_execution_idle_time_total[core]; /* Now compute the new total time. */ new_total_time = total_time + delta_time; - + /* Determine if a rollover on the total time is present. */ if (new_total_time < total_time) { - + /* Rollover. Set the total time to max value. */ new_total_time = (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE; } - + /* Now store back the total idle time. */ - _tx_execution_idle_time_total[core] = new_total_time; - + _tx_execution_idle_time_total[core] = new_total_time; + /* Disable the idle time measurement. */ _tx_execution_idle_time_last_start[core] = 0; } @@ -552,7 +547,7 @@ UINT core; /* Pickup the core index. */ core = TX_SMP_CORE_ID; - /* Determine if this is the first interrupt. Nested interrupts are all treated as + /* Determine if this is the first interrupt. Nested interrupts are all treated as general interrupt processing. */ if (_tx_thread_system_state[core] == 1) { @@ -562,17 +557,17 @@ UINT core; /* Pickup the last start time. */ last_start_time = _tx_execution_isr_time_last_start[core]; - + /* Determine how to calculate the difference. */ if (current_time >= last_start_time) { - + /* Simply subtract. */ delta_time = (EXECUTION_TIME) (current_time - last_start_time); } else { - + /* Timer wrapped, compute the delta assuming incrementing time counter. */ delta_time = (EXECUTION_TIME) (current_time + (((EXECUTION_TIME_SOURCE_TYPE) TX_EXECUTION_MAX_TIME_SOURCE) - last_start_time)); } @@ -582,18 +577,18 @@ UINT core; /* Now compute the new total time. */ new_total_time = total_time + delta_time; - + /* Determine if a rollover on the total time is present. */ if (new_total_time < total_time) { - + /* Rollover. Set the total time to max value. */ new_total_time = (EXECUTION_TIME) TX_EXECUTION_MAX_TIME_SOURCE; } - + /* Store back the new total time. */ _tx_execution_isr_time_total[core] = new_total_time; - + /* Pickup the current thread control block. */ thread_ptr = _tx_thread_current_ptr[core]; @@ -604,16 +599,16 @@ UINT core; /* Now determine if the thread will execution is going to occur immediately. */ if ((thread_ptr == _tx_thread_execute_ptr[core]) || (_tx_thread_preempt_disable)) { - + /* Yes, setup the thread last start time in the thread control block. */ thread_ptr -> tx_thread_execution_time_last_start = current_time; } } - + /* Determine if the system is now idle. */ if (_tx_thread_execute_ptr[core] == TX_NULL) { - + /* Yes, idle system. Pickup the start of idle time. */ _tx_execution_idle_time_last_start[core] = TX_EXECUTION_TIME_SOURCE; } @@ -710,8 +705,8 @@ UINT _tx_execution_thread_total_time_reset(void) { TX_INTERRUPT_SAVE_AREA - -TX_THREAD *thread_ptr; + +TX_THREAD *thread_ptr; UINT total_threads; UINT core; @@ -722,7 +717,7 @@ UINT core; /* Reset the total time for all cores. */ for (core = 0; core < TX_THREAD_SMP_MAX_CORES; core++) { - + _tx_execution_thread_time_total[core] = 0; } @@ -799,7 +794,7 @@ UINT core; /* Restore interrupts. */ TX_RESTORE - + /* Return success. */ return(TX_SUCCESS); } @@ -969,10 +964,10 @@ UINT core; *total_time = _tx_execution_thread_time_total[core]; } - + /* Restore interrupts. */ TX_RESTORE - + /* Return success. */ return(TX_SUCCESS); } @@ -1032,7 +1027,7 @@ UINT core; /* Return the total time. */ *total_time = _tx_execution_isr_time_total[core]; } - + /* Restore interrupts. */ TX_RESTORE @@ -1149,14 +1144,14 @@ UINT _tx_execution_core_thread_total_time_get(UINT core, EXECUTION_TIME *total_ /* Determine if the core is valid. */ if (core >= TX_THREAD_SMP_MAX_CORES) { - + /* Invalid core, return an error. */ return(TX_NOT_DONE); } /* Return the total thread time for the core. */ *total_time = _tx_execution_thread_time_total[core]; - + /* Return success. */ return(TX_SUCCESS); } @@ -1207,7 +1202,7 @@ UINT _tx_execution_core_isr_time_get(UINT core, EXECUTION_TIME *total_time) /* Determine if the core is valid. */ if (core >= TX_THREAD_SMP_MAX_CORES) { - + /* Invalid core, return an error. */ return(TX_NOT_DONE); } @@ -1264,7 +1259,7 @@ UINT _tx_execution_core_idle_time_get(UINT core, EXECUTION_TIME *total_time) /* Determine if the core is valid. */ if (core >= TX_THREAD_SMP_MAX_CORES) { - + /* Invalid core, return an error. */ return(TX_NOT_DONE); } diff --git a/utility/execution_profile_kit/smp_version/tx_execution_profile.h b/utility/execution_profile_kit/smp_version/tx_execution_profile.h index 1d1ac587..fee0e17c 100644 --- a/utility/execution_profile_kit/smp_version/tx_execution_profile.h +++ b/utility/execution_profile_kit/smp_version/tx_execution_profile.h @@ -1,10 +1,11 @@ /*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors + * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at * https://opensource.org/licenses/MIT. - * + * * SPDX-License-Identifier: MIT **************************************************************************/ @@ -24,20 +25,20 @@ #define TX_EXECUTION_PROFILE_H -/* The thread execution profile kit is designed to track thread execution time - based on the hardware timer defined by TX_EXECUTION_TIME_SOURCE and - TX_EXECUTION_MAX_TIME_SOURCE below. When the thread's total time reaches +/* The thread execution profile kit is designed to track thread execution time + based on the hardware timer defined by TX_EXECUTION_TIME_SOURCE and + TX_EXECUTION_MAX_TIME_SOURCE below. When the thread's total time reaches the maximum value, it remains there until the time is reset to 0 via a call - to tx_thread_execution_time_reset. There are several assumptions to the + to tx_thread_execution_time_reset. There are several assumptions to the operation of this kit, as follows: 1. In tx_port.h replace: #define TX_THREAD_EXTENSION_3" with: #define TX_THREAD_EXTENSION_3 unsigned long long tx_thread_execution_time_total; \ - unsigned long tx_thread_execution_time_last_start; + unsigned long tx_thread_execution_time_last_start; - 2. The TX_EXECUTION_TIME_SOURCE and TX_EXECUTION_MAX_TIME_SOURCE macros are + 2. The TX_EXECUTION_TIME_SOURCE and TX_EXECUTION_MAX_TIME_SOURCE macros are defined to utilize a local hardware time source. 3. The following routines are called from assembly code: @@ -46,9 +47,9 @@ VOID _tx_execution_isr_enter(void); VOID _tx_execution_isr_exit(void); - 4. The ThreadX library must be rebuilt with TX_ENABLE_EXECUTION_CHANGE_NOTIFY so - that these macros are expanded in the TX_THREAD structure and so the assembly code macros - are enabled to call the execution profile routines. + 4. The ThreadX library must be rebuilt with TX_ENABLE_EXECUTION_CHANGE_NOTIFY so + that these macros are expanded in the TX_THREAD structure and so the assembly code macros + are enabled to call the execution profile routines. 5. Add tx_execution_profile.c to the application build. */ |
