@@ -49,6 +49,7 @@ struct rcu_tasks_percpu {
49
49
struct list_head rtp_blkd_tasks ;
50
50
struct list_head rtp_exit_list ;
51
51
int cpu ;
52
+ int index ;
52
53
struct rcu_tasks * rtpp ;
53
54
};
54
55
@@ -110,6 +111,7 @@ struct rcu_tasks {
110
111
call_rcu_func_t call_func ;
111
112
unsigned int wait_state ;
112
113
struct rcu_tasks_percpu __percpu * rtpcpu ;
114
+ struct rcu_tasks_percpu * * rtpcp_array ;
113
115
int percpu_enqueue_shift ;
114
116
int percpu_enqueue_lim ;
115
117
int percpu_dequeue_lim ;
@@ -182,6 +184,8 @@ module_param(rcu_task_collapse_lim, int, 0444);
182
184
static int rcu_task_lazy_lim __read_mostly = 32 ;
183
185
module_param (rcu_task_lazy_lim , int , 0444 );
184
186
187
+ static int rcu_task_cpu_ids ;
188
+
185
189
/* RCU tasks grace-period state for debugging. */
186
190
#define RTGS_INIT 0
187
191
#define RTGS_WAIT_WAIT_CBS 1
@@ -245,6 +249,8 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
245
249
int cpu ;
246
250
int lim ;
247
251
int shift ;
252
+ int maxcpu ;
253
+ int index = 0 ;
248
254
249
255
if (rcu_task_enqueue_lim < 0 ) {
250
256
rcu_task_enqueue_lim = 1 ;
@@ -254,14 +260,9 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
254
260
}
255
261
lim = rcu_task_enqueue_lim ;
256
262
257
- if (lim > nr_cpu_ids )
258
- lim = nr_cpu_ids ;
259
- shift = ilog2 (nr_cpu_ids / lim );
260
- if (((nr_cpu_ids - 1 ) >> shift ) >= lim )
261
- shift ++ ;
262
- WRITE_ONCE (rtp -> percpu_enqueue_shift , shift );
263
- WRITE_ONCE (rtp -> percpu_dequeue_lim , lim );
264
- smp_store_release (& rtp -> percpu_enqueue_lim , lim );
263
+ rtp -> rtpcp_array = kcalloc (num_possible_cpus (), sizeof (struct rcu_tasks_percpu * ), GFP_KERNEL );
264
+ BUG_ON (!rtp -> rtpcp_array );
265
+
265
266
for_each_possible_cpu (cpu ) {
266
267
struct rcu_tasks_percpu * rtpcp = per_cpu_ptr (rtp -> rtpcpu , cpu );
267
268
@@ -273,14 +274,29 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
273
274
INIT_WORK (& rtpcp -> rtp_work , rcu_tasks_invoke_cbs_wq );
274
275
rtpcp -> cpu = cpu ;
275
276
rtpcp -> rtpp = rtp ;
277
+ rtpcp -> index = index ;
278
+ rtp -> rtpcp_array [index ] = rtpcp ;
279
+ index ++ ;
276
280
if (!rtpcp -> rtp_blkd_tasks .next )
277
281
INIT_LIST_HEAD (& rtpcp -> rtp_blkd_tasks );
278
282
if (!rtpcp -> rtp_exit_list .next )
279
283
INIT_LIST_HEAD (& rtpcp -> rtp_exit_list );
284
+ maxcpu = cpu ;
280
285
}
281
286
282
- pr_info ("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d.\n" , rtp -> name ,
283
- data_race (rtp -> percpu_enqueue_shift ), data_race (rtp -> percpu_enqueue_lim ), rcu_task_cb_adjust );
287
+ rcu_task_cpu_ids = maxcpu + 1 ;
288
+ if (lim > rcu_task_cpu_ids )
289
+ lim = rcu_task_cpu_ids ;
290
+ shift = ilog2 (rcu_task_cpu_ids / lim );
291
+ if (((rcu_task_cpu_ids - 1 ) >> shift ) >= lim )
292
+ shift ++ ;
293
+ WRITE_ONCE (rtp -> percpu_enqueue_shift , shift );
294
+ WRITE_ONCE (rtp -> percpu_dequeue_lim , lim );
295
+ smp_store_release (& rtp -> percpu_enqueue_lim , lim );
296
+
297
+ pr_info ("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d rcu_task_cpu_ids=%d.\n" ,
298
+ rtp -> name , data_race (rtp -> percpu_enqueue_shift ), data_race (rtp -> percpu_enqueue_lim ),
299
+ rcu_task_cb_adjust , rcu_task_cpu_ids );
284
300
}
285
301
286
302
// Compute wakeup time for lazy callback timer.
@@ -348,7 +364,7 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
348
364
rtpcp -> rtp_n_lock_retries = 0 ;
349
365
}
350
366
if (rcu_task_cb_adjust && ++ rtpcp -> rtp_n_lock_retries > rcu_task_contend_lim &&
351
- READ_ONCE (rtp -> percpu_enqueue_lim ) != nr_cpu_ids )
367
+ READ_ONCE (rtp -> percpu_enqueue_lim ) != rcu_task_cpu_ids )
352
368
needadjust = true; // Defer adjustment to avoid deadlock.
353
369
}
354
370
// Queuing callbacks before initialization not yet supported.
@@ -368,10 +384,10 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
368
384
raw_spin_unlock_irqrestore_rcu_node (rtpcp , flags );
369
385
if (unlikely (needadjust )) {
370
386
raw_spin_lock_irqsave (& rtp -> cbs_gbl_lock , flags );
371
- if (rtp -> percpu_enqueue_lim != nr_cpu_ids ) {
387
+ if (rtp -> percpu_enqueue_lim != rcu_task_cpu_ids ) {
372
388
WRITE_ONCE (rtp -> percpu_enqueue_shift , 0 );
373
- WRITE_ONCE (rtp -> percpu_dequeue_lim , nr_cpu_ids );
374
- smp_store_release (& rtp -> percpu_enqueue_lim , nr_cpu_ids );
389
+ WRITE_ONCE (rtp -> percpu_dequeue_lim , rcu_task_cpu_ids );
390
+ smp_store_release (& rtp -> percpu_enqueue_lim , rcu_task_cpu_ids );
375
391
pr_info ("Switching %s to per-CPU callback queuing.\n" , rtp -> name );
376
392
}
377
393
raw_spin_unlock_irqrestore (& rtp -> cbs_gbl_lock , flags );
@@ -444,6 +460,8 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
444
460
445
461
dequeue_limit = smp_load_acquire (& rtp -> percpu_dequeue_lim );
446
462
for (cpu = 0 ; cpu < dequeue_limit ; cpu ++ ) {
463
+ if (!cpu_possible (cpu ))
464
+ continue ;
447
465
struct rcu_tasks_percpu * rtpcp = per_cpu_ptr (rtp -> rtpcpu , cpu );
448
466
449
467
/* Advance and accelerate any new callbacks. */
@@ -481,7 +499,7 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
481
499
if (rcu_task_cb_adjust && ncbs <= rcu_task_collapse_lim ) {
482
500
raw_spin_lock_irqsave (& rtp -> cbs_gbl_lock , flags );
483
501
if (rtp -> percpu_enqueue_lim > 1 ) {
484
- WRITE_ONCE (rtp -> percpu_enqueue_shift , order_base_2 (nr_cpu_ids ));
502
+ WRITE_ONCE (rtp -> percpu_enqueue_shift , order_base_2 (rcu_task_cpu_ids ));
485
503
smp_store_release (& rtp -> percpu_enqueue_lim , 1 );
486
504
rtp -> percpu_dequeue_gpseq = get_state_synchronize_rcu ();
487
505
gpdone = false;
@@ -496,7 +514,9 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
496
514
pr_info ("Completing switch %s to CPU-0 callback queuing.\n" , rtp -> name );
497
515
}
498
516
if (rtp -> percpu_dequeue_lim == 1 ) {
499
- for (cpu = rtp -> percpu_dequeue_lim ; cpu < nr_cpu_ids ; cpu ++ ) {
517
+ for (cpu = rtp -> percpu_dequeue_lim ; cpu < rcu_task_cpu_ids ; cpu ++ ) {
518
+ if (!cpu_possible (cpu ))
519
+ continue ;
500
520
struct rcu_tasks_percpu * rtpcp = per_cpu_ptr (rtp -> rtpcpu , cpu );
501
521
502
522
WARN_ON_ONCE (rcu_segcblist_n_cbs (& rtpcp -> cblist ));
@@ -511,30 +531,32 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
511
531
// Advance callbacks and invoke any that are ready.
512
532
static void rcu_tasks_invoke_cbs (struct rcu_tasks * rtp , struct rcu_tasks_percpu * rtpcp )
513
533
{
514
- int cpu ;
515
- int cpunext ;
516
534
int cpuwq ;
517
535
unsigned long flags ;
518
536
int len ;
537
+ int index ;
519
538
struct rcu_head * rhp ;
520
539
struct rcu_cblist rcl = RCU_CBLIST_INITIALIZER (rcl );
521
540
struct rcu_tasks_percpu * rtpcp_next ;
522
541
523
- cpu = rtpcp -> cpu ;
524
- cpunext = cpu * 2 + 1 ;
525
- if (cpunext < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
526
- rtpcp_next = per_cpu_ptr (rtp -> rtpcpu , cpunext );
527
- cpuwq = rcu_cpu_beenfullyonline (cpunext ) ? cpunext : WORK_CPU_UNBOUND ;
528
- queue_work_on (cpuwq , system_wq , & rtpcp_next -> rtp_work );
529
- cpunext ++ ;
530
- if (cpunext < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
531
- rtpcp_next = per_cpu_ptr (rtp -> rtpcpu , cpunext );
532
- cpuwq = rcu_cpu_beenfullyonline (cpunext ) ? cpunext : WORK_CPU_UNBOUND ;
542
+ index = rtpcp -> index * 2 + 1 ;
543
+ if (index < num_possible_cpus ()) {
544
+ rtpcp_next = rtp -> rtpcp_array [index ];
545
+ if (rtpcp_next -> cpu < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
546
+ cpuwq = rcu_cpu_beenfullyonline (rtpcp_next -> cpu ) ? rtpcp_next -> cpu : WORK_CPU_UNBOUND ;
533
547
queue_work_on (cpuwq , system_wq , & rtpcp_next -> rtp_work );
548
+ index ++ ;
549
+ if (index < num_possible_cpus ()) {
550
+ rtpcp_next = rtp -> rtpcp_array [index ];
551
+ if (rtpcp_next -> cpu < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
552
+ cpuwq = rcu_cpu_beenfullyonline (rtpcp_next -> cpu ) ? rtpcp_next -> cpu : WORK_CPU_UNBOUND ;
553
+ queue_work_on (cpuwq , system_wq , & rtpcp_next -> rtp_work );
554
+ }
555
+ }
534
556
}
535
557
}
536
558
537
- if (rcu_segcblist_empty (& rtpcp -> cblist ) || ! cpu_possible ( cpu ) )
559
+ if (rcu_segcblist_empty (& rtpcp -> cblist ))
538
560
return ;
539
561
raw_spin_lock_irqsave_rcu_node (rtpcp , flags );
540
562
rcu_segcblist_advance (& rtpcp -> cblist , rcu_seq_current (& rtp -> tasks_gp_seq ));
0 commit comments