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)128 void  _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