aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-04-27 14:39:34 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-07-12 17:27:47 -0400
commit17ef2fe97c8c8e754e4a702c42f8e5b0ffadf4dd (patch)
tree57f08e5a676a2432fea98077ea5ff02626761e79
parentdee4f42298bba030e84035aca5c114f9fee8fa6a (diff)
rcu: Make rcutorture's batches-completed API use ->gp_seq
The rcutorture test invokes rcu_batches_started(), rcu_batches_completed(), rcu_batches_started_bh(), rcu_batches_completed_bh(), rcu_batches_started_sched(), and rcu_batches_completed_sched() to do grace-period consistency checks, and rcuperf uses the _completed variants for statistics. These functions use ->gpnum and ->completed. This commit therefore replaces them with rcu_get_gp_seq(), rcu_bh_get_gp_seq(), and rcu_sched_get_gp_seq(), adjusting rcutorture and rcuperf to make use of them. Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
-rw-r--r--kernel/rcu/rcu.h18
-rw-r--r--kernel/rcu/rcuperf.c26
-rw-r--r--kernel/rcu/rcutorture.c50
-rw-r--r--kernel/rcu/tree.c51
4 files changed, 45 insertions, 100 deletions
diff --git a/kernel/rcu/rcu.h b/kernel/rcu/rcu.h
index db0870acfdff..f0907f9f6cd0 100644
--- a/kernel/rcu/rcu.h
+++ b/kernel/rcu/rcu.h
@@ -463,12 +463,9 @@ void srcutorture_get_gp_data(enum rcutorture_type test_type,
463#endif 463#endif
464 464
465#ifdef CONFIG_TINY_RCU 465#ifdef CONFIG_TINY_RCU
466static inline unsigned long rcu_batches_started(void) { return 0; } 466static inline unsigned long rcu_get_gp_seq(void) { return 0; }
467static inline unsigned long rcu_batches_started_bh(void) { return 0; } 467static inline unsigned long rcu_bh_get_gp_seq(void) { return 0; }
468static inline unsigned long rcu_batches_started_sched(void) { return 0; } 468static inline unsigned long rcu_sched_get_gp_seq(void) { return 0; }
469static inline unsigned long rcu_batches_completed(void) { return 0; }
470static inline unsigned long rcu_batches_completed_bh(void) { return 0; }
471static inline unsigned long rcu_batches_completed_sched(void) { return 0; }
472static inline unsigned long rcu_exp_batches_completed(void) { return 0; } 469static inline unsigned long rcu_exp_batches_completed(void) { return 0; }
473static inline unsigned long rcu_exp_batches_completed_sched(void) { return 0; } 470static inline unsigned long rcu_exp_batches_completed_sched(void) { return 0; }
474static inline unsigned long 471static inline unsigned long
@@ -480,12 +477,9 @@ static inline void show_rcu_gp_kthreads(void) { }
480#else /* #ifdef CONFIG_TINY_RCU */ 477#else /* #ifdef CONFIG_TINY_RCU */
481extern unsigned long rcutorture_testseq; 478extern unsigned long rcutorture_testseq;
482extern unsigned long rcutorture_vernum; 479extern unsigned long rcutorture_vernum;
483unsigned long rcu_batches_started(void); 480unsigned long rcu_get_gp_seq(void);
484unsigned long rcu_batches_started_bh(void); 481unsigned long rcu_bh_get_gp_seq(void);
485unsigned long rcu_batches_started_sched(void); 482unsigned long rcu_sched_get_gp_seq(void);
486unsigned long rcu_batches_completed(void);
487unsigned long rcu_batches_completed_bh(void);
488unsigned long rcu_batches_completed_sched(void);
489unsigned long rcu_exp_batches_completed(void); 483unsigned long rcu_exp_batches_completed(void);
490unsigned long rcu_exp_batches_completed_sched(void); 484unsigned long rcu_exp_batches_completed_sched(void);
491unsigned long srcu_batches_completed(struct srcu_struct *sp); 485unsigned long srcu_batches_completed(struct srcu_struct *sp);
diff --git a/kernel/rcu/rcuperf.c b/kernel/rcu/rcuperf.c
index df29119b2013..2b5a613afcf3 100644
--- a/kernel/rcu/rcuperf.c
+++ b/kernel/rcu/rcuperf.c
@@ -138,8 +138,7 @@ struct rcu_perf_ops {
138 void (*cleanup)(void); 138 void (*cleanup)(void);
139 int (*readlock)(void); 139 int (*readlock)(void);
140 void (*readunlock)(int idx); 140 void (*readunlock)(int idx);
141 unsigned long (*started)(void); 141 unsigned long (*get_gp_seq)(void);
142 unsigned long (*completed)(void);
143 unsigned long (*exp_completed)(void); 142 unsigned long (*exp_completed)(void);
144 void (*async)(struct rcu_head *head, rcu_callback_t func); 143 void (*async)(struct rcu_head *head, rcu_callback_t func);
145 void (*gp_barrier)(void); 144 void (*gp_barrier)(void);
@@ -179,8 +178,7 @@ static struct rcu_perf_ops rcu_ops = {
179 .init = rcu_sync_perf_init, 178 .init = rcu_sync_perf_init,
180 .readlock = rcu_perf_read_lock, 179 .readlock = rcu_perf_read_lock,
181 .readunlock = rcu_perf_read_unlock, 180 .readunlock = rcu_perf_read_unlock,
182 .started = rcu_batches_started, 181 .get_gp_seq = rcu_get_gp_seq,
183 .completed = rcu_batches_completed,
184 .exp_completed = rcu_exp_batches_completed, 182 .exp_completed = rcu_exp_batches_completed,
185 .async = call_rcu, 183 .async = call_rcu,
186 .gp_barrier = rcu_barrier, 184 .gp_barrier = rcu_barrier,
@@ -209,8 +207,7 @@ static struct rcu_perf_ops rcu_bh_ops = {
209 .init = rcu_sync_perf_init, 207 .init = rcu_sync_perf_init,
210 .readlock = rcu_bh_perf_read_lock, 208 .readlock = rcu_bh_perf_read_lock,
211 .readunlock = rcu_bh_perf_read_unlock, 209 .readunlock = rcu_bh_perf_read_unlock,
212 .started = rcu_batches_started_bh, 210 .get_gp_seq = rcu_bh_get_gp_seq,
213 .completed = rcu_batches_completed_bh,
214 .exp_completed = rcu_exp_batches_completed_sched, 211 .exp_completed = rcu_exp_batches_completed_sched,
215 .async = call_rcu_bh, 212 .async = call_rcu_bh,
216 .gp_barrier = rcu_barrier_bh, 213 .gp_barrier = rcu_barrier_bh,
@@ -266,8 +263,7 @@ static struct rcu_perf_ops srcu_ops = {
266 .init = rcu_sync_perf_init, 263 .init = rcu_sync_perf_init,
267 .readlock = srcu_perf_read_lock, 264 .readlock = srcu_perf_read_lock,
268 .readunlock = srcu_perf_read_unlock, 265 .readunlock = srcu_perf_read_unlock,
269 .started = NULL, 266 .get_gp_seq = srcu_perf_completed,
270 .completed = srcu_perf_completed,
271 .exp_completed = srcu_perf_completed, 267 .exp_completed = srcu_perf_completed,
272 .async = srcu_call_rcu, 268 .async = srcu_call_rcu,
273 .gp_barrier = srcu_rcu_barrier, 269 .gp_barrier = srcu_rcu_barrier,
@@ -295,8 +291,7 @@ static struct rcu_perf_ops srcud_ops = {
295 .cleanup = srcu_sync_perf_cleanup, 291 .cleanup = srcu_sync_perf_cleanup,
296 .readlock = srcu_perf_read_lock, 292 .readlock = srcu_perf_read_lock,
297 .readunlock = srcu_perf_read_unlock, 293 .readunlock = srcu_perf_read_unlock,
298 .started = NULL, 294 .get_gp_seq = srcu_perf_completed,
299 .completed = srcu_perf_completed,
300 .exp_completed = srcu_perf_completed, 295 .exp_completed = srcu_perf_completed,
301 .async = srcu_call_rcu, 296 .async = srcu_call_rcu,
302 .gp_barrier = srcu_rcu_barrier, 297 .gp_barrier = srcu_rcu_barrier,
@@ -325,8 +320,7 @@ static struct rcu_perf_ops sched_ops = {
325 .init = rcu_sync_perf_init, 320 .init = rcu_sync_perf_init,
326 .readlock = sched_perf_read_lock, 321 .readlock = sched_perf_read_lock,
327 .readunlock = sched_perf_read_unlock, 322 .readunlock = sched_perf_read_unlock,
328 .started = rcu_batches_started_sched, 323 .get_gp_seq = rcu_sched_get_gp_seq,
329 .completed = rcu_batches_completed_sched,
330 .exp_completed = rcu_exp_batches_completed_sched, 324 .exp_completed = rcu_exp_batches_completed_sched,
331 .async = call_rcu_sched, 325 .async = call_rcu_sched,
332 .gp_barrier = rcu_barrier_sched, 326 .gp_barrier = rcu_barrier_sched,
@@ -353,8 +347,7 @@ static struct rcu_perf_ops tasks_ops = {
353 .init = rcu_sync_perf_init, 347 .init = rcu_sync_perf_init,
354 .readlock = tasks_perf_read_lock, 348 .readlock = tasks_perf_read_lock,
355 .readunlock = tasks_perf_read_unlock, 349 .readunlock = tasks_perf_read_unlock,
356 .started = rcu_no_completed, 350 .get_gp_seq = rcu_no_completed,
357 .completed = rcu_no_completed,
358 .async = call_rcu_tasks, 351 .async = call_rcu_tasks,
359 .gp_barrier = rcu_barrier_tasks, 352 .gp_barrier = rcu_barrier_tasks,
360 .sync = synchronize_rcu_tasks, 353 .sync = synchronize_rcu_tasks,
@@ -447,8 +440,7 @@ rcu_perf_writer(void *arg)
447 b_rcu_perf_writer_started = 440 b_rcu_perf_writer_started =
448 cur_ops->exp_completed() / 2; 441 cur_ops->exp_completed() / 2;
449 } else { 442 } else {
450 b_rcu_perf_writer_started = 443 b_rcu_perf_writer_started = cur_ops->get_gp_seq();
451 cur_ops->completed();
452 } 444 }
453 } 445 }
454 446
@@ -505,7 +497,7 @@ retry:
505 cur_ops->exp_completed() / 2; 497 cur_ops->exp_completed() / 2;
506 } else { 498 } else {
507 b_rcu_perf_writer_finished = 499 b_rcu_perf_writer_finished =
508 cur_ops->completed(); 500 cur_ops->get_gp_seq();
509 } 501 }
510 if (shutdown) { 502 if (shutdown) {
511 smp_mb(); /* Assign before wake. */ 503 smp_mb(); /* Assign before wake. */
diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c
index 5604bfac8df4..1f66597c7783 100644
--- a/kernel/rcu/rcutorture.c
+++ b/kernel/rcu/rcutorture.c
@@ -264,8 +264,7 @@ struct rcu_torture_ops {
264 int (*readlock)(void); 264 int (*readlock)(void);
265 void (*read_delay)(struct torture_random_state *rrsp); 265 void (*read_delay)(struct torture_random_state *rrsp);
266 void (*readunlock)(int idx); 266 void (*readunlock)(int idx);
267 unsigned long (*started)(void); 267 unsigned long (*get_gp_seq)(void);
268 unsigned long (*completed)(void);
269 void (*deferred_free)(struct rcu_torture *p); 268 void (*deferred_free)(struct rcu_torture *p);
270 void (*sync)(void); 269 void (*sync)(void);
271 void (*exp_sync)(void); 270 void (*exp_sync)(void);
@@ -305,10 +304,10 @@ static void rcu_read_delay(struct torture_random_state *rrsp)
305 * force_quiescent_state. */ 304 * force_quiescent_state. */
306 305
307 if (!(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms))) { 306 if (!(torture_random(rrsp) % (nrealreaders * 2000 * longdelay_ms))) {
308 started = cur_ops->completed(); 307 started = cur_ops->get_gp_seq();
309 ts = rcu_trace_clock_local(); 308 ts = rcu_trace_clock_local();
310 mdelay(longdelay_ms); 309 mdelay(longdelay_ms);
311 completed = cur_ops->completed(); 310 completed = cur_ops->get_gp_seq();
312 do_trace_rcu_torture_read(cur_ops->name, NULL, ts, 311 do_trace_rcu_torture_read(cur_ops->name, NULL, ts,
313 started, completed); 312 started, completed);
314 } 313 }
@@ -400,8 +399,7 @@ static struct rcu_torture_ops rcu_ops = {
400 .readlock = rcu_torture_read_lock, 399 .readlock = rcu_torture_read_lock,
401 .read_delay = rcu_read_delay, 400 .read_delay = rcu_read_delay,
402 .readunlock = rcu_torture_read_unlock, 401 .readunlock = rcu_torture_read_unlock,
403 .started = rcu_batches_started, 402 .get_gp_seq = rcu_get_gp_seq,
404 .completed = rcu_batches_completed,
405 .deferred_free = rcu_torture_deferred_free, 403 .deferred_free = rcu_torture_deferred_free,
406 .sync = synchronize_rcu, 404 .sync = synchronize_rcu,
407 .exp_sync = synchronize_rcu_expedited, 405 .exp_sync = synchronize_rcu_expedited,
@@ -442,8 +440,7 @@ static struct rcu_torture_ops rcu_bh_ops = {
442 .readlock = rcu_bh_torture_read_lock, 440 .readlock = rcu_bh_torture_read_lock,
443 .read_delay = rcu_read_delay, /* just reuse rcu's version. */ 441 .read_delay = rcu_read_delay, /* just reuse rcu's version. */
444 .readunlock = rcu_bh_torture_read_unlock, 442 .readunlock = rcu_bh_torture_read_unlock,
445 .started = rcu_batches_started_bh, 443 .get_gp_seq = rcu_bh_get_gp_seq,
446 .completed = rcu_batches_completed_bh,
447 .deferred_free = rcu_bh_torture_deferred_free, 444 .deferred_free = rcu_bh_torture_deferred_free,
448 .sync = synchronize_rcu_bh, 445 .sync = synchronize_rcu_bh,
449 .exp_sync = synchronize_rcu_bh_expedited, 446 .exp_sync = synchronize_rcu_bh_expedited,
@@ -486,8 +483,7 @@ static struct rcu_torture_ops rcu_busted_ops = {
486 .readlock = rcu_torture_read_lock, 483 .readlock = rcu_torture_read_lock,
487 .read_delay = rcu_read_delay, /* just reuse rcu's version. */ 484 .read_delay = rcu_read_delay, /* just reuse rcu's version. */
488 .readunlock = rcu_torture_read_unlock, 485 .readunlock = rcu_torture_read_unlock,
489 .started = rcu_no_completed, 486 .get_gp_seq = rcu_no_completed,
490 .completed = rcu_no_completed,
491 .deferred_free = rcu_busted_torture_deferred_free, 487 .deferred_free = rcu_busted_torture_deferred_free,
492 .sync = synchronize_rcu_busted, 488 .sync = synchronize_rcu_busted,
493 .exp_sync = synchronize_rcu_busted, 489 .exp_sync = synchronize_rcu_busted,
@@ -575,8 +571,7 @@ static struct rcu_torture_ops srcu_ops = {
575 .readlock = srcu_torture_read_lock, 571 .readlock = srcu_torture_read_lock,
576 .read_delay = srcu_read_delay, 572 .read_delay = srcu_read_delay,
577 .readunlock = srcu_torture_read_unlock, 573 .readunlock = srcu_torture_read_unlock,
578 .started = NULL, 574 .get_gp_seq = srcu_torture_completed,
579 .completed = srcu_torture_completed,
580 .deferred_free = srcu_torture_deferred_free, 575 .deferred_free = srcu_torture_deferred_free,
581 .sync = srcu_torture_synchronize, 576 .sync = srcu_torture_synchronize,
582 .exp_sync = srcu_torture_synchronize_expedited, 577 .exp_sync = srcu_torture_synchronize_expedited,
@@ -613,8 +608,7 @@ static struct rcu_torture_ops srcud_ops = {
613 .readlock = srcu_torture_read_lock, 608 .readlock = srcu_torture_read_lock,
614 .read_delay = srcu_read_delay, 609 .read_delay = srcu_read_delay,
615 .readunlock = srcu_torture_read_unlock, 610 .readunlock = srcu_torture_read_unlock,
616 .started = NULL, 611 .get_gp_seq = srcu_torture_completed,
617 .completed = srcu_torture_completed,
618 .deferred_free = srcu_torture_deferred_free, 612 .deferred_free = srcu_torture_deferred_free,
619 .sync = srcu_torture_synchronize, 613 .sync = srcu_torture_synchronize,
620 .exp_sync = srcu_torture_synchronize_expedited, 614 .exp_sync = srcu_torture_synchronize_expedited,
@@ -651,8 +645,7 @@ static struct rcu_torture_ops sched_ops = {
651 .readlock = sched_torture_read_lock, 645 .readlock = sched_torture_read_lock,
652 .read_delay = rcu_read_delay, /* just reuse rcu's version. */ 646 .read_delay = rcu_read_delay, /* just reuse rcu's version. */
653 .readunlock = sched_torture_read_unlock, 647 .readunlock = sched_torture_read_unlock,
654 .started = rcu_batches_started_sched, 648 .get_gp_seq = rcu_sched_get_gp_seq,
655 .completed = rcu_batches_completed_sched,
656 .deferred_free = rcu_sched_torture_deferred_free, 649 .deferred_free = rcu_sched_torture_deferred_free,
657 .sync = synchronize_sched, 650 .sync = synchronize_sched,
658 .exp_sync = synchronize_sched_expedited, 651 .exp_sync = synchronize_sched_expedited,
@@ -690,8 +683,7 @@ static struct rcu_torture_ops tasks_ops = {
690 .readlock = tasks_torture_read_lock, 683 .readlock = tasks_torture_read_lock,
691 .read_delay = rcu_read_delay, /* just reuse rcu's version. */ 684 .read_delay = rcu_read_delay, /* just reuse rcu's version. */
692 .readunlock = tasks_torture_read_unlock, 685 .readunlock = tasks_torture_read_unlock,
693 .started = rcu_no_completed, 686 .get_gp_seq = rcu_no_completed,
694 .completed = rcu_no_completed,
695 .deferred_free = rcu_tasks_torture_deferred_free, 687 .deferred_free = rcu_tasks_torture_deferred_free,
696 .sync = synchronize_rcu_tasks, 688 .sync = synchronize_rcu_tasks,
697 .exp_sync = synchronize_rcu_tasks, 689 .exp_sync = synchronize_rcu_tasks,
@@ -1104,10 +1096,7 @@ static void rcu_torture_timer(struct timer_list *unused)
1104 unsigned long long ts; 1096 unsigned long long ts;
1105 1097
1106 idx = cur_ops->readlock(); 1098 idx = cur_ops->readlock();
1107 if (cur_ops->started) 1099 started = cur_ops->get_gp_seq();
1108 started = cur_ops->started();
1109 else
1110 started = cur_ops->completed();
1111 ts = rcu_trace_clock_local(); 1100 ts = rcu_trace_clock_local();
1112 p = rcu_dereference_check(rcu_torture_current, 1101 p = rcu_dereference_check(rcu_torture_current,
1113 rcu_read_lock_bh_held() || 1102 rcu_read_lock_bh_held() ||
@@ -1131,7 +1120,7 @@ static void rcu_torture_timer(struct timer_list *unused)
1131 /* Should not happen, but... */ 1120 /* Should not happen, but... */
1132 pipe_count = RCU_TORTURE_PIPE_LEN; 1121 pipe_count = RCU_TORTURE_PIPE_LEN;
1133 } 1122 }
1134 completed = cur_ops->completed(); 1123 completed = cur_ops->get_gp_seq();
1135 if (pipe_count > 1) { 1124 if (pipe_count > 1) {
1136 do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts, 1125 do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, ts,
1137 started, completed); 1126 started, completed);
@@ -1139,8 +1128,8 @@ static void rcu_torture_timer(struct timer_list *unused)
1139 } 1128 }
1140 __this_cpu_inc(rcu_torture_count[pipe_count]); 1129 __this_cpu_inc(rcu_torture_count[pipe_count]);
1141 completed = completed - started; 1130 completed = completed - started;
1142 if (cur_ops->started) 1131 if (completed > ULONG_MAX >> 1)
1143 completed++; 1132 completed = 0; /* Not all gp_seq have full range. */
1144 if (completed > RCU_TORTURE_PIPE_LEN) { 1133 if (completed > RCU_TORTURE_PIPE_LEN) {
1145 /* Should not happen, but... */ 1134 /* Should not happen, but... */
1146 completed = RCU_TORTURE_PIPE_LEN; 1135 completed = RCU_TORTURE_PIPE_LEN;
@@ -1187,10 +1176,7 @@ rcu_torture_reader(void *arg)
1187 mod_timer(&t, jiffies + 1); 1176 mod_timer(&t, jiffies + 1);
1188 } 1177 }
1189 idx = cur_ops->readlock(); 1178 idx = cur_ops->readlock();
1190 if (cur_ops->started) 1179 started = cur_ops->get_gp_seq();
1191 started = cur_ops->started();
1192 else
1193 started = cur_ops->completed();
1194 ts = rcu_trace_clock_local(); 1180 ts = rcu_trace_clock_local();
1195 p = rcu_dereference_check(rcu_torture_current, 1181 p = rcu_dereference_check(rcu_torture_current,
1196 rcu_read_lock_bh_held() || 1182 rcu_read_lock_bh_held() ||
@@ -1212,7 +1198,7 @@ rcu_torture_reader(void *arg)
1212 /* Should not happen, but... */ 1198 /* Should not happen, but... */
1213 pipe_count = RCU_TORTURE_PIPE_LEN; 1199 pipe_count = RCU_TORTURE_PIPE_LEN;
1214 } 1200 }
1215 completed = cur_ops->completed(); 1201 completed = cur_ops->get_gp_seq();
1216 if (pipe_count > 1) { 1202 if (pipe_count > 1) {
1217 do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu, 1203 do_trace_rcu_torture_read(cur_ops->name, &p->rtort_rcu,
1218 ts, started, completed); 1204 ts, started, completed);
@@ -1220,8 +1206,8 @@ rcu_torture_reader(void *arg)
1220 } 1206 }
1221 __this_cpu_inc(rcu_torture_count[pipe_count]); 1207 __this_cpu_inc(rcu_torture_count[pipe_count]);
1222 completed = completed - started; 1208 completed = completed - started;
1223 if (cur_ops->started) 1209 if (completed > ULONG_MAX >> 1)
1224 completed++; 1210 completed = 0; /* Not all gp_seq have full range. */
1225 if (completed > RCU_TORTURE_PIPE_LEN) { 1211 if (completed > RCU_TORTURE_PIPE_LEN) {
1226 /* Should not happen, but... */ 1212 /* Should not happen, but... */
1227 completed = RCU_TORTURE_PIPE_LEN; 1213 completed = RCU_TORTURE_PIPE_LEN;
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 3c3af7e2758f..547112bec26a 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -530,58 +530,31 @@ static void force_quiescent_state(struct rcu_state *rsp);
530static int rcu_pending(void); 530static int rcu_pending(void);
531 531
532/* 532/*
533 * Return the number of RCU batches started thus far for debug & stats. 533 * Return the number of RCU GPs completed thus far for debug & stats.
534 */ 534 */
535unsigned long rcu_batches_started(void) 535unsigned long rcu_get_gp_seq(void)
536{ 536{
537 return rcu_state_p->gpnum; 537 return rcu_seq_ctr(READ_ONCE(rcu_state_p->gp_seq));
538} 538}
539EXPORT_SYMBOL_GPL(rcu_batches_started); 539EXPORT_SYMBOL_GPL(rcu_get_gp_seq);
540 540
541/* 541/*
542 * Return the number of RCU-sched batches started thus far for debug & stats. 542 * Return the number of RCU-sched GPs completed thus far for debug & stats.
543 */ 543 */
544unsigned long rcu_batches_started_sched(void) 544unsigned long rcu_sched_get_gp_seq(void)
545{ 545{
546 return rcu_sched_state.gpnum; 546 return rcu_seq_ctr(READ_ONCE(rcu_sched_state.gp_seq));
547} 547}
548EXPORT_SYMBOL_GPL(rcu_batches_started_sched); 548EXPORT_SYMBOL_GPL(rcu_sched_get_gp_seq);
549 549
550/* 550/*
551 * Return the number of RCU BH batches started thus far for debug & stats. 551 * Return the number of RCU-bh GPs completed thus far for debug & stats.
552 */ 552 */
553unsigned long rcu_batches_started_bh(void) 553unsigned long rcu_bh_get_gp_seq(void)
554{ 554{
555 return rcu_bh_state.gpnum; 555 return rcu_seq_ctr(READ_ONCE(rcu_bh_state.gp_seq));
556} 556}
557EXPORT_SYMBOL_GPL(rcu_batches_started_bh); 557EXPORT_SYMBOL_GPL(rcu_bh_get_gp_seq);
558
559/*
560 * Return the number of RCU batches completed thus far for debug & stats.
561 */
562unsigned long rcu_batches_completed(void)
563{
564 return rcu_state_p->completed;
565}
566EXPORT_SYMBOL_GPL(rcu_batches_completed);
567
568/*
569 * Return the number of RCU-sched batches completed thus far for debug & stats.
570 */
571unsigned long rcu_batches_completed_sched(void)
572{
573 return rcu_sched_state.completed;
574}
575EXPORT_SYMBOL_GPL(rcu_batches_completed_sched);
576
577/*
578 * Return the number of RCU BH batches completed thus far for debug & stats.
579 */
580unsigned long rcu_batches_completed_bh(void)
581{
582 return rcu_bh_state.completed;
583}
584EXPORT_SYMBOL_GPL(rcu_batches_completed_bh);
585 558
586/* 559/*
587 * Return the number of RCU expedited batches completed thus far for 560 * Return the number of RCU expedited batches completed thus far for