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