@@ -193,80 +193,81 @@ void __init free_bootmem_cpumask_var(cpumask_var_t mask)
193
193
}
194
194
#endif
195
195
196
- static int find_nearest_node (int node , bool * used )
196
+ static int find_nearest_node (int node , nodemask_t nodes )
197
197
{
198
198
int i , min_dist , node_id = -1 ;
199
199
200
200
/* Choose the first unused node to compare */
201
- for (i = 0 ; i < nr_node_ids ; i ++ ) {
202
- if (used [ i ] == false ) {
201
+ for (i = 0 ; i < nr_node_ids ; i ++ )
202
+ if (! node_isset ( i , nodes ) ) {
203
203
min_dist = node_distance (node , i );
204
204
node_id = i ;
205
205
break ;
206
206
}
207
- }
208
207
209
208
/* Compare and return the nearest node */
210
- for (i = 0 ; i < nr_node_ids ; i ++ ) {
211
- if (node_distance (node , i ) < min_dist && used [i ] == false) {
209
+ for (i = 0 ; i < nr_node_ids ; i ++ )
210
+ if (!node_isset (i , nodes ) &&
211
+ node_distance (node , i ) < min_dist ) {
212
212
min_dist = node_distance (node , i );
213
213
node_id = i ;
214
214
}
215
- }
216
215
217
216
return node_id ;
218
217
}
219
218
220
219
/**
221
220
* cpumask_local_spread - select the i'th cpu with local numa cpu's first
222
- * @i : index number
221
+ * @cpu_index : index number
223
222
* @node: local numa_node
224
223
*
225
224
* This function selects an online CPU according to a numa aware policy;
226
- * local cpus are returned first, followed by the next one which is the
227
- * nearest unused NUMA node based on NUMA distance, then it wraps around.
225
+ * Loop through all the online CPUs on the system. Start with the CPUs on
226
+ * 'node', then fall back to CPUs on NUMA nodes which are increasingly far
227
+ * away.
228
228
*
229
- * It's not very efficient, but useful for setup.
229
+ * This function is not very efficient, especially for large 'cpu_index'
230
+ * because it loops over the same CPUs on each call and does not remember
231
+ * its state from previous calls, but it is useful for setup.
230
232
*/
231
- unsigned int cpumask_local_spread (unsigned int i , int node )
233
+ unsigned int cpumask_local_spread (unsigned int cpu_index , int node )
232
234
{
233
- static DEFINE_SPINLOCK (spread_lock );
234
- static bool used [MAX_NUMNODES ];
235
- unsigned long flags ;
236
- int cpu , hk_flags , j , id ;
235
+ int cpu , hk_flags , j , ncpus , id ;
237
236
const struct cpumask * mask ;
237
+ struct cpumask nmsk ;
238
+ nodemask_t nodes_msk ;
238
239
239
240
hk_flags = HK_FLAG_DOMAIN | HK_FLAG_MANAGED_IRQ ;
240
241
mask = housekeeping_cpumask (hk_flags );
241
242
/* Wrap: we always want a cpu. */
242
- i %= cpumask_weight (mask );
243
+ cpu_index %= cpumask_weight (mask );
243
244
244
245
if (node == NUMA_NO_NODE ) {
245
246
for_each_cpu (cpu , mask ) {
246
- if (i -- == 0 )
247
+ if (cpu_index -- == 0 )
247
248
return cpu ;
248
249
}
249
250
} else {
250
- spin_lock_irqsave (& spread_lock , flags );
251
- memset (used , 0 , nr_node_ids * sizeof (bool ));
252
251
/* select node according to the distance from local node */
252
+ nodes_clear (nodes_msk );
253
253
for (j = 0 ; j < nr_node_ids ; j ++ ) {
254
- id = find_nearest_node (node , used );
254
+ id = find_nearest_node (node , nodes_msk );
255
255
if (id < 0 )
256
256
break ;
257
-
258
- for_each_cpu_and (cpu , cpumask_of_node (id ), mask )
259
- if (i -- == 0 ) {
260
- spin_unlock_irqrestore (& spread_lock ,
261
- flags );
257
+ cpumask_and (& nmsk , mask , cpumask_of_node (id ));
258
+ ncpus = cpumask_weight (& nmsk );
259
+ if (cpu_index >= ncpus ) {
260
+ cpu_index -= ncpus ;
261
+ node_set (id , nodes_msk );
262
+ continue ;
263
+ }
264
+ for_each_cpu (cpu , & nmsk )
265
+ if (cpu_index -- == 0 )
262
266
return cpu ;
263
- }
264
- used [id ] = true;
265
267
}
266
- spin_unlock_irqrestore (& spread_lock , flags );
267
268
268
269
for_each_cpu (cpu , mask )
269
- if (i -- == 0 )
270
+ if (cpu_index -- == 0 )
270
271
return cpu ;
271
272
}
272
273
BUG ();
0 commit comments