/*************************************************************************** * Copyright (c) 2024 Microsoft Corporation * * 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 **************************************************************************/ /**************************************************************************/ /**************************************************************************/ /** */ /** ThreadX Component */ /** */ /** Thread */ /** */ /**************************************************************************/ /**************************************************************************/ #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE /* Include necessary system files. */ #include "tx_api.h" #include "tx_initialize.h" #include "tx_timer.h" #include "tx_thread.h" /* Determine if debugging is enabled. */ #ifdef TX_THREAD_SMP_DEBUG_ENABLE /* Define the maximum number of debug entries. */ #ifndef TX_THREAD_SMP_MAX_DEBUG_ENTRIES #define TX_THREAD_SMP_MAX_DEBUG_ENTRIES 100 #endif /* Define the debug information structures. */ typedef struct TX_THREAD_SMP_DEBUG_ENTRY_STRUCT { ULONG tx_thread_smp_debug_entry_id; ULONG tx_thread_smp_debug_entry_suspend; ULONG tx_thread_smp_debug_entry_core_index; ULONG tx_thread_smp_debug_entry_time; ULONG tx_thread_smp_debug_entry_timer_clock; TX_THREAD *tx_thread_smp_debug_entry_thread; UINT tx_thread_smp_debug_entry_thread_priority; UINT tx_thread_smp_debug_entry_thread_threshold; ULONG tx_thread_smp_debug_entry_thread_core_control; TX_THREAD *tx_thread_smp_debug_entry_current_thread; TX_THREAD_SMP_PROTECT tx_thread_smp_debug_protection; ULONG tx_thread_smp_debug_entry_preempt_disable; ULONG tx_thread_smp_debug_entry_system_state[TX_THREAD_SMP_MAX_CORES]; #ifndef TX_DISABLE_PREEMPTION_THRESHOLD ULONG tx_thread_smp_debug_entry_preempt_map; #endif TX_THREAD *tx_thread_smp_debug_entry_preempt_thread; ULONG tx_thread_smp_debug_entry_priority_map; ULONG tx_thread_smp_debug_entry_reschedule_pending; TX_THREAD *tx_thread_smp_debug_entry_current_threads[TX_THREAD_SMP_MAX_CORES]; TX_THREAD *tx_thread_smp_debug_entry_execute_threads[TX_THREAD_SMP_MAX_CORES]; } TX_THREAD_SMP_DEBUG_ENTRY_INFO; /* Define the circular array of debug entries. */ TX_THREAD_SMP_DEBUG_ENTRY_INFO _tx_thread_smp_debug_info_array[TX_THREAD_SMP_MAX_DEBUG_ENTRIES]; /* Define the starting index. */ ULONG _tx_thread_smp_debug_info_current_index; /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _tx_thread_smp_debug_entry_insert PORTABLE SMP */ /* 6.1 */ /* AUTHOR */ /* */ /* William E. Lamie, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ /* This function is responsible for making an entry in the circular */ /* debug log. */ /* */ /* INPUT */ /* */ /* id ID of event */ /* suspend Flag set to true for suspend */ /* events */ /* thread_ptr Specified thread */ /* */ /* OUTPUT */ /* */ /* None */ /* */ /* CALLS */ /* */ /* _tx_thread_smp_time_get Get global time stamp */ /* */ /* CALLED BY */ /* */ /* Internal routines */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 William E. Lamie Initial Version 6.1 */ /* */ /**************************************************************************/ void _tx_thread_smp_debug_entry_insert(ULONG id, ULONG suspend, VOID *thread_void_ptr) { ULONG i; ULONG core_index; TX_THREAD_SMP_DEBUG_ENTRY_INFO *entry_ptr; TX_THREAD *thread_ptr; /* Spin, if an error is detected. No sense in populating the debug after the error occurs. */ while (_tx_thread_smp_system_error) { /* Spin here! */ } /* Check for a bad current index. */ while (_tx_thread_smp_debug_info_current_index >= TX_THREAD_SMP_MAX_DEBUG_ENTRIES) { /* Spin here! */ } thread_ptr = (TX_THREAD *) thread_void_ptr; /* It is assumed that interrupts are locked out at this point. */ /* Setup pointer to debug entry. */ entry_ptr = &_tx_thread_smp_debug_info_array[_tx_thread_smp_debug_info_current_index++]; /* Check for wrap on the index. */ if (_tx_thread_smp_debug_info_current_index >= TX_THREAD_SMP_MAX_DEBUG_ENTRIES) { /* Wrap back to 0. */ _tx_thread_smp_debug_info_current_index = 0; } /* Get the index. */ core_index = TX_SMP_CORE_ID; /* We know at this point that multithreading and interrupts are disabled... so start populating the array. */ entry_ptr -> tx_thread_smp_debug_entry_id = id; entry_ptr -> tx_thread_smp_debug_entry_suspend = suspend; entry_ptr -> tx_thread_smp_debug_entry_thread = thread_ptr; entry_ptr -> tx_thread_smp_debug_entry_time = _tx_thread_smp_time_get(); entry_ptr -> tx_thread_smp_debug_entry_timer_clock = _tx_timer_system_clock; entry_ptr -> tx_thread_smp_debug_entry_core_index = core_index; entry_ptr -> tx_thread_smp_debug_entry_current_thread = _tx_thread_current_ptr[core_index]; if (entry_ptr -> tx_thread_smp_debug_entry_current_thread) { entry_ptr -> tx_thread_smp_debug_entry_thread_priority = (entry_ptr -> tx_thread_smp_debug_entry_current_thread) -> tx_thread_priority; entry_ptr -> tx_thread_smp_debug_entry_thread_threshold = (entry_ptr -> tx_thread_smp_debug_entry_current_thread) -> tx_thread_preempt_threshold; entry_ptr -> tx_thread_smp_debug_entry_thread_core_control = (entry_ptr -> tx_thread_smp_debug_entry_current_thread) -> tx_thread_smp_core_control; } else { entry_ptr -> tx_thread_smp_debug_entry_thread_priority = 0; entry_ptr -> tx_thread_smp_debug_entry_thread_threshold = 0; entry_ptr -> tx_thread_smp_debug_entry_thread_core_control = 0; } entry_ptr -> tx_thread_smp_debug_protection = _tx_thread_smp_protection; entry_ptr -> tx_thread_smp_debug_entry_preempt_disable = _tx_thread_preempt_disable; #ifndef TX_DISABLE_PREEMPTION_THRESHOLD entry_ptr -> tx_thread_smp_debug_entry_preempt_map = _tx_thread_preempted_maps[0]; #endif entry_ptr -> tx_thread_smp_debug_entry_preempt_thread = _tx_thread_preemption__threshold_scheduled; entry_ptr -> tx_thread_smp_debug_entry_priority_map = _tx_thread_priority_maps[0]; #ifndef TX_THREAD_SMP_DYNAMIC_CORE_MAX /* Loop to save the current and execute lists. */ for (i = 0; i < TX_THREAD_SMP_MAX_CORES; i++) #else /* Loop to save the current and execute lists. */ for (i = 0; i < _tx_thread_smp_max_cores; i++) #endif { /* Save the pointers. */ entry_ptr -> tx_thread_smp_debug_entry_current_threads[i] = _tx_thread_current_ptr[i]; entry_ptr -> tx_thread_smp_debug_entry_execute_threads[i] = _tx_thread_execute_ptr[i]; /* Save the system state. */ entry_ptr -> tx_thread_smp_debug_entry_system_state[i] = _tx_thread_system_state[i]; } } #endif