1 /*************************************************************************** 2 * Copyright (c) 2024 Microsoft Corporation 3 * 4 * This program and the accompanying materials are made available under the 5 * terms of the MIT License which is available at 6 * https://opensource.org/licenses/MIT. 7 * 8 * SPDX-License-Identifier: MIT 9 **************************************************************************/ 10 11 12 /**************************************************************************/ 13 /**************************************************************************/ 14 /** */ 15 /** ThreadX Component */ 16 /** */ 17 /** Thread */ 18 /** */ 19 /**************************************************************************/ 20 /**************************************************************************/ 21 22 #define TX_SOURCE_CODE 23 #define TX_THREAD_SMP_SOURCE_CODE 24 25 26 /* Include necessary system files. */ 27 28 29 #include "tx_api.h" 30 #include "tx_initialize.h" 31 #include "tx_timer.h" 32 #include "tx_thread.h" 33 34 35 /* Determine if debugging is enabled. */ 36 37 #ifdef TX_THREAD_SMP_DEBUG_ENABLE 38 39 40 /* Define the maximum number of debug entries. */ 41 42 #ifndef TX_THREAD_SMP_MAX_DEBUG_ENTRIES 43 #define TX_THREAD_SMP_MAX_DEBUG_ENTRIES 100 44 #endif 45 46 47 /* Define the debug information structures. */ 48 49 typedef struct TX_THREAD_SMP_DEBUG_ENTRY_STRUCT 50 { 51 52 ULONG tx_thread_smp_debug_entry_id; 53 ULONG tx_thread_smp_debug_entry_suspend; 54 ULONG tx_thread_smp_debug_entry_core_index; 55 ULONG tx_thread_smp_debug_entry_time; 56 ULONG tx_thread_smp_debug_entry_timer_clock; 57 TX_THREAD *tx_thread_smp_debug_entry_thread; 58 UINT tx_thread_smp_debug_entry_thread_priority; 59 UINT tx_thread_smp_debug_entry_thread_threshold; 60 ULONG tx_thread_smp_debug_entry_thread_core_control; 61 TX_THREAD *tx_thread_smp_debug_entry_current_thread; 62 TX_THREAD_SMP_PROTECT tx_thread_smp_debug_protection; 63 ULONG tx_thread_smp_debug_entry_preempt_disable; 64 ULONG tx_thread_smp_debug_entry_system_state[TX_THREAD_SMP_MAX_CORES]; 65 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD 66 ULONG tx_thread_smp_debug_entry_preempt_map; 67 #endif 68 TX_THREAD *tx_thread_smp_debug_entry_preempt_thread; 69 ULONG tx_thread_smp_debug_entry_priority_map; 70 ULONG tx_thread_smp_debug_entry_reschedule_pending; 71 TX_THREAD *tx_thread_smp_debug_entry_current_threads[TX_THREAD_SMP_MAX_CORES]; 72 TX_THREAD *tx_thread_smp_debug_entry_execute_threads[TX_THREAD_SMP_MAX_CORES]; 73 74 } TX_THREAD_SMP_DEBUG_ENTRY_INFO; 75 76 77 /* Define the circular array of debug entries. */ 78 79 TX_THREAD_SMP_DEBUG_ENTRY_INFO _tx_thread_smp_debug_info_array[TX_THREAD_SMP_MAX_DEBUG_ENTRIES]; 80 81 82 /* Define the starting index. */ 83 84 ULONG _tx_thread_smp_debug_info_current_index; 85 86 87 /**************************************************************************/ 88 /* */ 89 /* FUNCTION RELEASE */ 90 /* */ 91 /* _tx_thread_smp_debug_entry_insert PORTABLE SMP */ 92 /* 6.1 */ 93 /* AUTHOR */ 94 /* */ 95 /* William E. Lamie, Microsoft Corporation */ 96 /* */ 97 /* DESCRIPTION */ 98 /* */ 99 /* This function is responsible for making an entry in the circular */ 100 /* debug log. */ 101 /* */ 102 /* INPUT */ 103 /* */ 104 /* id ID of event */ 105 /* suspend Flag set to true for suspend */ 106 /* events */ 107 /* thread_ptr Specified thread */ 108 /* */ 109 /* OUTPUT */ 110 /* */ 111 /* None */ 112 /* */ 113 /* CALLS */ 114 /* */ 115 /* _tx_thread_smp_time_get Get global time stamp */ 116 /* */ 117 /* CALLED BY */ 118 /* */ 119 /* Internal routines */ 120 /* */ 121 /* RELEASE HISTORY */ 122 /* */ 123 /* DATE NAME DESCRIPTION */ 124 /* */ 125 /* 09-30-2020 William E. Lamie Initial Version 6.1 */ 126 /* */ 127 /**************************************************************************/ _tx_thread_smp_debug_entry_insert(ULONG id,ULONG suspend,VOID * thread_void_ptr)128void _tx_thread_smp_debug_entry_insert(ULONG id, ULONG suspend, VOID *thread_void_ptr) 129 { 130 131 ULONG i; 132 ULONG core_index; 133 TX_THREAD_SMP_DEBUG_ENTRY_INFO *entry_ptr; 134 TX_THREAD *thread_ptr; 135 136 137 /* Spin, if an error is detected. No sense in populating the debug after the error occurs. */ 138 while (_tx_thread_smp_system_error) 139 { 140 141 /* Spin here! */ 142 } 143 144 /* Check for a bad current index. */ 145 while (_tx_thread_smp_debug_info_current_index >= TX_THREAD_SMP_MAX_DEBUG_ENTRIES) 146 { 147 148 /* Spin here! */ 149 } 150 151 thread_ptr = (TX_THREAD *) thread_void_ptr; 152 153 /* It is assumed that interrupts are locked out at this point. */ 154 155 /* Setup pointer to debug entry. */ 156 entry_ptr = &_tx_thread_smp_debug_info_array[_tx_thread_smp_debug_info_current_index++]; 157 158 /* Check for wrap on the index. */ 159 if (_tx_thread_smp_debug_info_current_index >= TX_THREAD_SMP_MAX_DEBUG_ENTRIES) 160 { 161 162 /* Wrap back to 0. */ 163 _tx_thread_smp_debug_info_current_index = 0; 164 } 165 166 /* Get the index. */ 167 core_index = TX_SMP_CORE_ID; 168 169 /* We know at this point that multithreading and interrupts are disabled... so start populating the array. */ 170 entry_ptr -> tx_thread_smp_debug_entry_id = id; 171 entry_ptr -> tx_thread_smp_debug_entry_suspend = suspend; 172 entry_ptr -> tx_thread_smp_debug_entry_thread = thread_ptr; 173 entry_ptr -> tx_thread_smp_debug_entry_time = _tx_thread_smp_time_get(); 174 entry_ptr -> tx_thread_smp_debug_entry_timer_clock = _tx_timer_system_clock; 175 entry_ptr -> tx_thread_smp_debug_entry_core_index = core_index; 176 entry_ptr -> tx_thread_smp_debug_entry_current_thread = _tx_thread_current_ptr[core_index]; 177 if (entry_ptr -> tx_thread_smp_debug_entry_current_thread) 178 { 179 180 entry_ptr -> tx_thread_smp_debug_entry_thread_priority = (entry_ptr -> tx_thread_smp_debug_entry_current_thread) -> tx_thread_priority; 181 entry_ptr -> tx_thread_smp_debug_entry_thread_threshold = (entry_ptr -> tx_thread_smp_debug_entry_current_thread) -> tx_thread_preempt_threshold; 182 entry_ptr -> tx_thread_smp_debug_entry_thread_core_control = (entry_ptr -> tx_thread_smp_debug_entry_current_thread) -> tx_thread_smp_core_control; 183 } 184 else 185 { 186 187 entry_ptr -> tx_thread_smp_debug_entry_thread_priority = 0; 188 entry_ptr -> tx_thread_smp_debug_entry_thread_threshold = 0; 189 entry_ptr -> tx_thread_smp_debug_entry_thread_core_control = 0; 190 } 191 192 entry_ptr -> tx_thread_smp_debug_protection = _tx_thread_smp_protection; 193 entry_ptr -> tx_thread_smp_debug_entry_preempt_disable = _tx_thread_preempt_disable; 194 #ifndef TX_DISABLE_PREEMPTION_THRESHOLD 195 entry_ptr -> tx_thread_smp_debug_entry_preempt_map = _tx_thread_preempted_maps[0]; 196 #endif 197 entry_ptr -> tx_thread_smp_debug_entry_preempt_thread = _tx_thread_preemption__threshold_scheduled; 198 entry_ptr -> tx_thread_smp_debug_entry_priority_map = _tx_thread_priority_maps[0]; 199 200 #ifndef TX_THREAD_SMP_DYNAMIC_CORE_MAX 201 202 /* Loop to save the current and execute lists. */ 203 for (i = 0; i < TX_THREAD_SMP_MAX_CORES; i++) 204 #else 205 206 /* Loop to save the current and execute lists. */ 207 for (i = 0; i < _tx_thread_smp_max_cores; i++) 208 #endif 209 { 210 211 /* Save the pointers. */ 212 entry_ptr -> tx_thread_smp_debug_entry_current_threads[i] = _tx_thread_current_ptr[i]; 213 entry_ptr -> tx_thread_smp_debug_entry_execute_threads[i] = _tx_thread_execute_ptr[i]; 214 215 /* Save the system state. */ 216 entry_ptr -> tx_thread_smp_debug_entry_system_state[i] = _tx_thread_system_state[i]; 217 } 218 } 219 220 221 #endif 222 223