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 - High Level SMP Support */
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 #include "tx_api.h"
30 #include "tx_initialize.h"
31 #include "tx_timer.h"
32 #include "tx_thread.h"
33
34
35 /**************************************************************************/
36 /* */
37 /* FUNCTION RELEASE */
38 /* */
39 /* _tx_thread_smp_core_exclude PORTABLE SMP */
40 /* 6.1 */
41 /* AUTHOR */
42 /* */
43 /* William E. Lamie, Microsoft Corporation */
44 /* */
45 /* DESCRIPTION */
46 /* */
47 /* This function allows the application to exclude one or more cores */
48 /* from executing the specified thread. */
49 /* */
50 /* INPUT */
51 /* */
52 /* thread_ptr Pointer to the thread */
53 /* exclusion_map Bit map of exclusion list, */
54 /* where bit 0 set means that */
55 /* this thread cannot run on */
56 /* core0, etc. */
57 /* */
58 /* OUTPUT */
59 /* */
60 /* Status */
61 /* */
62 /* CALLS */
63 /* */
64 /* _tx_thread_smp_rebalance_execute_list Build execution list */
65 /* _tx_thread_system_return System return */
66 /* */
67 /* CALLED BY */
68 /* */
69 /* Application Code */
70 /* */
71 /* RELEASE HISTORY */
72 /* */
73 /* DATE NAME DESCRIPTION */
74 /* */
75 /* 09-30-2020 William E. Lamie Initial Version 6.1 */
76 /* */
77 /**************************************************************************/
_tx_thread_smp_core_exclude(TX_THREAD * thread_ptr,ULONG exclusion_map)78 UINT _tx_thread_smp_core_exclude(TX_THREAD *thread_ptr, ULONG exclusion_map)
79 {
80
81 TX_INTERRUPT_SAVE_AREA
82
83 UINT core_index;
84 UINT new_mapped_core;
85 ULONG mapped_core;
86 ULONG available_cores;
87 UINT restore_needed;
88 UINT status;
89
90
91 /* Default status to success. */
92 status = TX_SUCCESS;
93
94 /* First, make sure the thread pointer is valid. */
95 if (thread_ptr == TX_NULL)
96 {
97
98 /* Return pointer error. */
99 status = TX_THREAD_ERROR;
100 }
101
102 /* Check for valid ID. */
103 else if (thread_ptr -> tx_thread_id != TX_THREAD_ID)
104 {
105
106 /* Return pointer error. */
107 status = TX_THREAD_ERROR;
108 }
109 else
110 {
111
112 /* Disable interrupts. */
113 TX_DISABLE
114
115 /* Set the restore needed flag. */
116 restore_needed = TX_TRUE;
117
118 #ifdef TX_THREAD_SMP_DEBUG_ENABLE
119
120 /* Debug entry. */
121 _tx_thread_smp_debug_entry_insert(2, 0, thread_ptr);
122 #endif
123
124 /* Build the bitmap for the last mapped core. */
125 mapped_core = (((ULONG) 1) << thread_ptr -> tx_thread_smp_core_mapped);
126
127 /* Calculate the available cores map. */
128 available_cores = (~exclusion_map) & ((ULONG) TX_THREAD_SMP_CORE_MASK);
129
130 /* Save the excluded and available cores. */
131 thread_ptr -> tx_thread_smp_cores_excluded = exclusion_map;
132 thread_ptr -> tx_thread_smp_cores_allowed = available_cores;
133
134 /* Determine if this is within the now available cores. */
135 if ((mapped_core & available_cores) == ((ULONG) 0))
136 {
137
138 /* Determine if there are any cores available. */
139 if (available_cores == ((ULONG) 0))
140 {
141
142 /* No cores are available, simply set the last running core to 0. */
143 thread_ptr -> tx_thread_smp_core_mapped = ((UINT) 0);
144 }
145 else
146 {
147
148 /* No, we need set the last mapped core to a valid core. */
149 TX_LOWEST_SET_BIT_CALCULATE(available_cores, new_mapped_core)
150
151 /* Now setup the last core mapped. */
152 thread_ptr -> tx_thread_smp_core_mapped = new_mapped_core;
153 }
154 }
155
156 #ifdef TX_THREAD_SMP_DEBUG_ENABLE
157
158 /* Determine if the thread is in a ready state. */
159 if (thread_ptr -> tx_thread_state != TX_READY)
160 {
161
162
163 /* Debug entry. */
164 _tx_thread_smp_debug_entry_insert(3, 0, thread_ptr);
165
166 }
167 #endif
168
169 /* Determine if the thread is ready. */
170 if (thread_ptr -> tx_thread_state == TX_READY)
171 {
172
173 /* Pickup the index. */
174 core_index = TX_SMP_CORE_ID;
175
176 /* Call the rebalance routine. This routine maps cores and ready threads. */
177 _tx_thread_smp_rebalance_execute_list(core_index);
178
179 #ifdef TX_THREAD_SMP_DEBUG_ENABLE
180
181 /* Debug entry. */
182 _tx_thread_smp_debug_entry_insert(3, 0, thread_ptr);
183 #endif
184
185 /* Determine if this thread needs to return to the system. */
186
187 /* Is there a difference between the current and execute thread pointers? */
188 if (_tx_thread_execute_ptr[core_index] != _tx_thread_current_ptr[core_index])
189 {
190
191 /* Yes, check to see if we are at the thread level. */
192 if (_tx_thread_system_state[core_index] == ((ULONG) 0))
193 {
194
195 /* At the thread level, check for the preempt disable flag being set. */
196 if (_tx_thread_preempt_disable == ((UINT) 0))
197 {
198
199 #ifndef TX_NOT_INTERRUPTABLE
200
201 /* Increment the preempt disable flag in order to keep the protection. */
202 _tx_thread_preempt_disable++;
203
204 /* Restore interrupts. */
205 TX_RESTORE
206 #endif
207
208 /* Transfer control to the system so the scheduler can execute
209 the next thread. */
210 _tx_thread_system_return();
211
212 #ifdef TX_NOT_INTERRUPTABLE
213
214 /* Restore interrupts. */
215 TX_RESTORE
216 #endif
217
218 /* Clear the restore needed flag, since the interrupt poster/protection has been done. */
219 restore_needed = TX_FALSE;
220 }
221 }
222 }
223 }
224
225 /* Determine if the protection still needs to be restored. */
226 if (restore_needed == TX_TRUE)
227 {
228
229 /* Restore interrupts. */
230 TX_RESTORE
231 }
232 }
233
234 /* Return status. */
235 return(status);
236 }
237
238