Skip to content

Commit f1fd0e0

Browse files
paulmckrcuNeeraj Upadhyay
authored andcommitted
rcuscale: Count outstanding callbacks per-task rather than per-CPU
The current rcu_scale_writer() asynchronous grace-period testing uses a per-CPU counter to track the number of outstanding callbacks. This is subject to CPU-imbalance errors when tasks migrate from one CPU to another between the time that the counter is incremented and the callback is queued, and additionally in kernels configured such that callbacks can be invoked on some CPU other than the one that queued it. This commit therefore arranges for per-task callback counts, thus avoiding any issues with migration of either tasks or callbacks. Reported-by: Vlastimil Babka <[email protected]> Signed-off-by: "Paul E. McKenney" <[email protected]> Signed-off-by: Neeraj Upadhyay <[email protected]>
1 parent 554f07a commit f1fd0e0

File tree

1 file changed

+6
-4
lines changed

1 file changed

+6
-4
lines changed

kernel/rcu/rcuscale.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ struct writer_mblock {
114114

115115
struct writer_freelist {
116116
struct llist_head ws_lhg;
117+
atomic_t ws_inflight;
117118
struct llist_head ____cacheline_internodealigned_in_smp ws_lhp;
118119
struct writer_mblock *ws_mblocks;
119120
};
@@ -136,7 +137,6 @@ static u64 t_rcu_scale_writer_started;
136137
static u64 t_rcu_scale_writer_finished;
137138
static unsigned long b_rcu_gp_test_started;
138139
static unsigned long b_rcu_gp_test_finished;
139-
static DEFINE_PER_CPU(atomic_t, n_async_inflight);
140140

141141
#define MAX_MEAS 10000
142142
#define MIN_MEAS 100
@@ -520,8 +520,9 @@ static void rcu_scale_free(struct writer_mblock *wmbp)
520520
static void rcu_scale_async_cb(struct rcu_head *rhp)
521521
{
522522
struct writer_mblock *wmbp = container_of(rhp, struct writer_mblock, wmb_rh);
523+
struct writer_freelist *wflp = wmbp->wmb_wfl;
523524

524-
atomic_dec(this_cpu_ptr(&n_async_inflight));
525+
atomic_dec(&wflp->ws_inflight);
525526
rcu_scale_free(wmbp);
526527
}
527528

@@ -541,6 +542,7 @@ rcu_scale_writer(void *arg)
541542
DEFINE_TORTURE_RANDOM(tr);
542543
u64 *wdp;
543544
u64 *wdpp = writer_durations[me];
545+
struct writer_freelist *wflp = &writer_freelists[me];
544546
struct writer_mblock *wmbp = NULL;
545547

546548
VERBOSE_SCALEOUT_STRING("rcu_scale_writer task started");
@@ -584,8 +586,8 @@ rcu_scale_writer(void *arg)
584586
if (gp_async && !WARN_ON_ONCE(!cur_ops->async)) {
585587
if (!wmbp)
586588
wmbp = rcu_scale_alloc(me);
587-
if (wmbp && atomic_read(this_cpu_ptr(&n_async_inflight)) < gp_async_max) {
588-
atomic_inc(this_cpu_ptr(&n_async_inflight));
589+
if (wmbp && atomic_read(&wflp->ws_inflight) < gp_async_max) {
590+
atomic_inc(&wflp->ws_inflight);
589591
cur_ops->async(&wmbp->wmb_rh, rcu_scale_async_cb);
590592
wmbp = NULL;
591593
gp_succeeded = true;

0 commit comments

Comments
 (0)