@@ -34,6 +34,7 @@ typedef void (*postgp_func_t)(struct rcu_tasks *rtp);
34
34
* @rtp_blkd_tasks: List of tasks blocked as readers.
35
35
* @rtp_exit_list: List of tasks in the latter portion of do_exit().
36
36
* @cpu: CPU number corresponding to this entry.
37
+ * @index: Index of this CPU in rtpcp_array of the rcu_tasks structure.
37
38
* @rtpp: Pointer to the rcu_tasks structure.
38
39
*/
39
40
struct rcu_tasks_percpu {
@@ -49,6 +50,7 @@ struct rcu_tasks_percpu {
49
50
struct list_head rtp_blkd_tasks ;
50
51
struct list_head rtp_exit_list ;
51
52
int cpu ;
53
+ int index ;
52
54
struct rcu_tasks * rtpp ;
53
55
};
54
56
@@ -75,6 +77,7 @@ struct rcu_tasks_percpu {
75
77
* @postgp_func: This flavor's post-grace-period function (optional).
76
78
* @call_func: This flavor's call_rcu()-equivalent function.
77
79
* @rtpcpu: This flavor's rcu_tasks_percpu structure.
80
+ * @rtpcp_array: Array of pointers to rcu_tasks_percpu structure of CPUs in cpu_possible_mask.
78
81
* @percpu_enqueue_shift: Shift down CPU ID this much when enqueuing callbacks.
79
82
* @percpu_enqueue_lim: Number of per-CPU callback queues in use for enqueuing.
80
83
* @percpu_dequeue_lim: Number of per-CPU callback queues in use for dequeuing.
@@ -108,6 +111,7 @@ struct rcu_tasks {
108
111
postgp_func_t postgp_func ;
109
112
call_rcu_func_t call_func ;
110
113
struct rcu_tasks_percpu __percpu * rtpcpu ;
114
+ struct rcu_tasks_percpu * * rtpcp_array ;
111
115
int percpu_enqueue_shift ;
112
116
int percpu_enqueue_lim ;
113
117
int percpu_dequeue_lim ;
@@ -181,6 +185,8 @@ module_param(rcu_task_collapse_lim, int, 0444);
181
185
static int rcu_task_lazy_lim __read_mostly = 32 ;
182
186
module_param (rcu_task_lazy_lim , int , 0444 );
183
187
188
+ static int rcu_task_cpu_ids ;
189
+
184
190
/* RCU tasks grace-period state for debugging. */
185
191
#define RTGS_INIT 0
186
192
#define RTGS_WAIT_WAIT_CBS 1
@@ -245,6 +251,8 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
245
251
unsigned long flags ;
246
252
int lim ;
247
253
int shift ;
254
+ int maxcpu ;
255
+ int index = 0 ;
248
256
249
257
if (rcu_task_enqueue_lim < 0 ) {
250
258
rcu_task_enqueue_lim = 1 ;
@@ -254,14 +262,9 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
254
262
}
255
263
lim = rcu_task_enqueue_lim ;
256
264
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 );
265
+ rtp -> rtpcp_array = kcalloc (num_possible_cpus (), sizeof (struct rcu_tasks_percpu * ), GFP_KERNEL );
266
+ BUG_ON (!rtp -> rtpcp_array );
267
+
265
268
for_each_possible_cpu (cpu ) {
266
269
struct rcu_tasks_percpu * rtpcp = per_cpu_ptr (rtp -> rtpcpu , cpu );
267
270
@@ -275,14 +278,29 @@ static void cblist_init_generic(struct rcu_tasks *rtp)
275
278
INIT_WORK (& rtpcp -> rtp_work , rcu_tasks_invoke_cbs_wq );
276
279
rtpcp -> cpu = cpu ;
277
280
rtpcp -> rtpp = rtp ;
281
+ rtpcp -> index = index ;
282
+ rtp -> rtpcp_array [index ] = rtpcp ;
283
+ index ++ ;
278
284
if (!rtpcp -> rtp_blkd_tasks .next )
279
285
INIT_LIST_HEAD (& rtpcp -> rtp_blkd_tasks );
280
286
if (!rtpcp -> rtp_exit_list .next )
281
287
INIT_LIST_HEAD (& rtpcp -> rtp_exit_list );
288
+ maxcpu = cpu ;
282
289
}
283
290
284
- pr_info ("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d.\n" , rtp -> name ,
285
- data_race (rtp -> percpu_enqueue_shift ), data_race (rtp -> percpu_enqueue_lim ), rcu_task_cb_adjust );
291
+ rcu_task_cpu_ids = maxcpu + 1 ;
292
+ if (lim > rcu_task_cpu_ids )
293
+ lim = rcu_task_cpu_ids ;
294
+ shift = ilog2 (rcu_task_cpu_ids / lim );
295
+ if (((rcu_task_cpu_ids - 1 ) >> shift ) >= lim )
296
+ shift ++ ;
297
+ WRITE_ONCE (rtp -> percpu_enqueue_shift , shift );
298
+ WRITE_ONCE (rtp -> percpu_dequeue_lim , lim );
299
+ smp_store_release (& rtp -> percpu_enqueue_lim , lim );
300
+
301
+ pr_info ("%s: Setting shift to %d and lim to %d rcu_task_cb_adjust=%d rcu_task_cpu_ids=%d.\n" ,
302
+ rtp -> name , data_race (rtp -> percpu_enqueue_shift ), data_race (rtp -> percpu_enqueue_lim ),
303
+ rcu_task_cb_adjust , rcu_task_cpu_ids );
286
304
}
287
305
288
306
// Compute wakeup time for lazy callback timer.
@@ -350,7 +368,7 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
350
368
rtpcp -> rtp_n_lock_retries = 0 ;
351
369
}
352
370
if (rcu_task_cb_adjust && ++ rtpcp -> rtp_n_lock_retries > rcu_task_contend_lim &&
353
- READ_ONCE (rtp -> percpu_enqueue_lim ) != nr_cpu_ids )
371
+ READ_ONCE (rtp -> percpu_enqueue_lim ) != rcu_task_cpu_ids )
354
372
needadjust = true; // Defer adjustment to avoid deadlock.
355
373
}
356
374
// Queuing callbacks before initialization not yet supported.
@@ -370,10 +388,10 @@ static void call_rcu_tasks_generic(struct rcu_head *rhp, rcu_callback_t func,
370
388
raw_spin_unlock_irqrestore_rcu_node (rtpcp , flags );
371
389
if (unlikely (needadjust )) {
372
390
raw_spin_lock_irqsave (& rtp -> cbs_gbl_lock , flags );
373
- if (rtp -> percpu_enqueue_lim != nr_cpu_ids ) {
391
+ if (rtp -> percpu_enqueue_lim != rcu_task_cpu_ids ) {
374
392
WRITE_ONCE (rtp -> percpu_enqueue_shift , 0 );
375
- WRITE_ONCE (rtp -> percpu_dequeue_lim , nr_cpu_ids );
376
- smp_store_release (& rtp -> percpu_enqueue_lim , nr_cpu_ids );
393
+ WRITE_ONCE (rtp -> percpu_dequeue_lim , rcu_task_cpu_ids );
394
+ smp_store_release (& rtp -> percpu_enqueue_lim , rcu_task_cpu_ids );
377
395
pr_info ("Switching %s to per-CPU callback queuing.\n" , rtp -> name );
378
396
}
379
397
raw_spin_unlock_irqrestore (& rtp -> cbs_gbl_lock , flags );
@@ -446,6 +464,8 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
446
464
447
465
dequeue_limit = smp_load_acquire (& rtp -> percpu_dequeue_lim );
448
466
for (cpu = 0 ; cpu < dequeue_limit ; cpu ++ ) {
467
+ if (!cpu_possible (cpu ))
468
+ continue ;
449
469
struct rcu_tasks_percpu * rtpcp = per_cpu_ptr (rtp -> rtpcpu , cpu );
450
470
451
471
/* Advance and accelerate any new callbacks. */
@@ -483,7 +503,7 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
483
503
if (rcu_task_cb_adjust && ncbs <= rcu_task_collapse_lim ) {
484
504
raw_spin_lock_irqsave (& rtp -> cbs_gbl_lock , flags );
485
505
if (rtp -> percpu_enqueue_lim > 1 ) {
486
- WRITE_ONCE (rtp -> percpu_enqueue_shift , order_base_2 (nr_cpu_ids ));
506
+ WRITE_ONCE (rtp -> percpu_enqueue_shift , order_base_2 (rcu_task_cpu_ids ));
487
507
smp_store_release (& rtp -> percpu_enqueue_lim , 1 );
488
508
rtp -> percpu_dequeue_gpseq = get_state_synchronize_rcu ();
489
509
gpdone = false;
@@ -498,7 +518,9 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
498
518
pr_info ("Completing switch %s to CPU-0 callback queuing.\n" , rtp -> name );
499
519
}
500
520
if (rtp -> percpu_dequeue_lim == 1 ) {
501
- for (cpu = rtp -> percpu_dequeue_lim ; cpu < nr_cpu_ids ; cpu ++ ) {
521
+ for (cpu = rtp -> percpu_dequeue_lim ; cpu < rcu_task_cpu_ids ; cpu ++ ) {
522
+ if (!cpu_possible (cpu ))
523
+ continue ;
502
524
struct rcu_tasks_percpu * rtpcp = per_cpu_ptr (rtp -> rtpcpu , cpu );
503
525
504
526
WARN_ON_ONCE (rcu_segcblist_n_cbs (& rtpcp -> cblist ));
@@ -513,30 +535,32 @@ static int rcu_tasks_need_gpcb(struct rcu_tasks *rtp)
513
535
// Advance callbacks and invoke any that are ready.
514
536
static void rcu_tasks_invoke_cbs (struct rcu_tasks * rtp , struct rcu_tasks_percpu * rtpcp )
515
537
{
516
- int cpu ;
517
- int cpunext ;
518
538
int cpuwq ;
519
539
unsigned long flags ;
520
540
int len ;
541
+ int index ;
521
542
struct rcu_head * rhp ;
522
543
struct rcu_cblist rcl = RCU_CBLIST_INITIALIZER (rcl );
523
544
struct rcu_tasks_percpu * rtpcp_next ;
524
545
525
- cpu = rtpcp -> cpu ;
526
- cpunext = cpu * 2 + 1 ;
527
- if (cpunext < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
528
- rtpcp_next = per_cpu_ptr (rtp -> rtpcpu , cpunext );
529
- cpuwq = rcu_cpu_beenfullyonline (cpunext ) ? cpunext : WORK_CPU_UNBOUND ;
530
- queue_work_on (cpuwq , system_wq , & rtpcp_next -> rtp_work );
531
- cpunext ++ ;
532
- if (cpunext < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
533
- rtpcp_next = per_cpu_ptr (rtp -> rtpcpu , cpunext );
534
- cpuwq = rcu_cpu_beenfullyonline (cpunext ) ? cpunext : WORK_CPU_UNBOUND ;
546
+ index = rtpcp -> index * 2 + 1 ;
547
+ if (index < num_possible_cpus ()) {
548
+ rtpcp_next = rtp -> rtpcp_array [index ];
549
+ if (rtpcp_next -> cpu < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
550
+ cpuwq = rcu_cpu_beenfullyonline (rtpcp_next -> cpu ) ? rtpcp_next -> cpu : WORK_CPU_UNBOUND ;
535
551
queue_work_on (cpuwq , system_wq , & rtpcp_next -> rtp_work );
552
+ index ++ ;
553
+ if (index < num_possible_cpus ()) {
554
+ rtpcp_next = rtp -> rtpcp_array [index ];
555
+ if (rtpcp_next -> cpu < smp_load_acquire (& rtp -> percpu_dequeue_lim )) {
556
+ cpuwq = rcu_cpu_beenfullyonline (rtpcp_next -> cpu ) ? rtpcp_next -> cpu : WORK_CPU_UNBOUND ;
557
+ queue_work_on (cpuwq , system_wq , & rtpcp_next -> rtp_work );
558
+ }
559
+ }
536
560
}
537
561
}
538
562
539
- if (rcu_segcblist_empty (& rtpcp -> cblist ) || ! cpu_possible ( cpu ) )
563
+ if (rcu_segcblist_empty (& rtpcp -> cblist ))
540
564
return ;
541
565
raw_spin_lock_irqsave_rcu_node (rtpcp , flags );
542
566
rcu_segcblist_advance (& rtpcp -> cblist , rcu_seq_current (& rtp -> tasks_gp_seq ));
0 commit comments