aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/trace/events/rcu.h38
-rw-r--r--kernel/rcutiny.c10
-rw-r--r--kernel/rcutiny_plugin.h25
-rw-r--r--kernel/rcutree.c8
4 files changed, 68 insertions, 13 deletions
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h
index c75418c3ccb8..d2d88bed891b 100644
--- a/include/trace/events/rcu.h
+++ b/include/trace/events/rcu.h
@@ -461,27 +461,46 @@ TRACE_EVENT(rcu_invoke_kfree_callback,
461 461
462/* 462/*
463 * Tracepoint for exiting rcu_do_batch after RCU callbacks have been 463 * Tracepoint for exiting rcu_do_batch after RCU callbacks have been
464 * invoked. The first argument is the name of the RCU flavor and 464 * invoked. The first argument is the name of the RCU flavor,
465 * the second argument is number of callbacks actually invoked. 465 * the second argument is number of callbacks actually invoked,
466 * the third argument (cb) is whether or not any of the callbacks that
467 * were ready to invoke at the beginning of this batch are still
468 * queued, the fourth argument (nr) is the return value of need_resched(),
469 * the fifth argument (iit) is 1 if the current task is the idle task,
470 * and the sixth argument (risk) is the return value from
471 * rcu_is_callbacks_kthread().
466 */ 472 */
467TRACE_EVENT(rcu_batch_end, 473TRACE_EVENT(rcu_batch_end,
468 474
469 TP_PROTO(char *rcuname, int callbacks_invoked), 475 TP_PROTO(char *rcuname, int callbacks_invoked,
476 bool cb, bool nr, bool iit, bool risk),
470 477
471 TP_ARGS(rcuname, callbacks_invoked), 478 TP_ARGS(rcuname, callbacks_invoked, cb, nr, iit, risk),
472 479
473 TP_STRUCT__entry( 480 TP_STRUCT__entry(
474 __field(char *, rcuname) 481 __field(char *, rcuname)
475 __field(int, callbacks_invoked) 482 __field(int, callbacks_invoked)
483 __field(bool, cb)
484 __field(bool, nr)
485 __field(bool, iit)
486 __field(bool, risk)
476 ), 487 ),
477 488
478 TP_fast_assign( 489 TP_fast_assign(
479 __entry->rcuname = rcuname; 490 __entry->rcuname = rcuname;
480 __entry->callbacks_invoked = callbacks_invoked; 491 __entry->callbacks_invoked = callbacks_invoked;
481 ), 492 __entry->cb = cb;
482 493 __entry->nr = nr;
483 TP_printk("%s CBs-invoked=%d", 494 __entry->iit = iit;
484 __entry->rcuname, __entry->callbacks_invoked) 495 __entry->risk = risk;
496 ),
497
498 TP_printk("%s CBs-invoked=%d idle=%c%c%c%c",
499 __entry->rcuname, __entry->callbacks_invoked,
500 __entry->cb ? 'C' : '.',
501 __entry->nr ? 'S' : '.',
502 __entry->iit ? 'I' : '.',
503 __entry->risk ? 'R' : '.')
485); 504);
486 505
487/* 506/*
@@ -524,7 +543,8 @@ TRACE_EVENT(rcu_torture_read,
524#define trace_rcu_batch_start(rcuname, qlen, blimit) do { } while (0) 543#define trace_rcu_batch_start(rcuname, qlen, blimit) do { } while (0)
525#define trace_rcu_invoke_callback(rcuname, rhp) do { } while (0) 544#define trace_rcu_invoke_callback(rcuname, rhp) do { } while (0)
526#define trace_rcu_invoke_kfree_callback(rcuname, rhp, offset) do { } while (0) 545#define trace_rcu_invoke_kfree_callback(rcuname, rhp, offset) do { } while (0)
527#define trace_rcu_batch_end(rcuname, callbacks_invoked) do { } while (0) 546#define trace_rcu_batch_end(rcuname, callbacks_invoked, cb, nr, iit, risk) \
547 do { } while (0)
528#define trace_rcu_torture_read(rcutorturename, rhp) do { } while (0) 548#define trace_rcu_torture_read(rcutorturename, rhp) do { } while (0)
529 549
530#endif /* #else #ifdef CONFIG_RCU_TRACE */ 550#endif /* #else #ifdef CONFIG_RCU_TRACE */
diff --git a/kernel/rcutiny.c b/kernel/rcutiny.c
index e5bd94954fa3..977296dca0a4 100644
--- a/kernel/rcutiny.c
+++ b/kernel/rcutiny.c
@@ -259,7 +259,11 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
259 /* If no RCU callbacks ready to invoke, just return. */ 259 /* If no RCU callbacks ready to invoke, just return. */
260 if (&rcp->rcucblist == rcp->donetail) { 260 if (&rcp->rcucblist == rcp->donetail) {
261 RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, -1)); 261 RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, -1));
262 RCU_TRACE(trace_rcu_batch_end(rcp->name, 0)); 262 RCU_TRACE(trace_rcu_batch_end(rcp->name, 0,
263 ACCESS_ONCE(rcp->rcucblist),
264 need_resched(),
265 is_idle_task(current),
266 rcu_is_callbacks_kthread()));
263 return; 267 return;
264 } 268 }
265 269
@@ -288,7 +292,9 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
288 RCU_TRACE(cb_count++); 292 RCU_TRACE(cb_count++);
289 } 293 }
290 RCU_TRACE(rcu_trace_sub_qlen(rcp, cb_count)); 294 RCU_TRACE(rcu_trace_sub_qlen(rcp, cb_count));
291 RCU_TRACE(trace_rcu_batch_end(rcp->name, cb_count)); 295 RCU_TRACE(trace_rcu_batch_end(rcp->name, cb_count, 0, need_resched(),
296 is_idle_task(current),
297 rcu_is_callbacks_kthread()));
292} 298}
293 299
294static void rcu_process_callbacks(struct softirq_action *unused) 300static void rcu_process_callbacks(struct softirq_action *unused)
diff --git a/kernel/rcutiny_plugin.h b/kernel/rcutiny_plugin.h
index 2b0484a5dc28..dfa97cbb3910 100644
--- a/kernel/rcutiny_plugin.h
+++ b/kernel/rcutiny_plugin.h
@@ -885,6 +885,19 @@ static void invoke_rcu_callbacks(void)
885 wake_up(&rcu_kthread_wq); 885 wake_up(&rcu_kthread_wq);
886} 886}
887 887
888#ifdef CONFIG_RCU_TRACE
889
890/*
891 * Is the current CPU running the RCU-callbacks kthread?
892 * Caller must have preemption disabled.
893 */
894static bool rcu_is_callbacks_kthread(void)
895{
896 return rcu_kthread_task == current;
897}
898
899#endif /* #ifdef CONFIG_RCU_TRACE */
900
888/* 901/*
889 * This kthread invokes RCU callbacks whose grace periods have 902 * This kthread invokes RCU callbacks whose grace periods have
890 * elapsed. It is awakened as needed, and takes the place of the 903 * elapsed. It is awakened as needed, and takes the place of the
@@ -938,6 +951,18 @@ void invoke_rcu_callbacks(void)
938 raise_softirq(RCU_SOFTIRQ); 951 raise_softirq(RCU_SOFTIRQ);
939} 952}
940 953
954#ifdef CONFIG_RCU_TRACE
955
956/*
957 * There is no callback kthread, so this thread is never it.
958 */
959static bool rcu_is_callbacks_kthread(void)
960{
961 return false;
962}
963
964#endif /* #ifdef CONFIG_RCU_TRACE */
965
941void rcu_init(void) 966void rcu_init(void)
942{ 967{
943 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks); 968 open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
diff --git a/kernel/rcutree.c b/kernel/rcutree.c
index 2b2e1a996a65..6c4a6722abfd 100644
--- a/kernel/rcutree.c
+++ b/kernel/rcutree.c
@@ -1373,7 +1373,9 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
1373 /* If no callbacks are ready, just return.*/ 1373 /* If no callbacks are ready, just return.*/
1374 if (!cpu_has_callbacks_ready_to_invoke(rdp)) { 1374 if (!cpu_has_callbacks_ready_to_invoke(rdp)) {
1375 trace_rcu_batch_start(rsp->name, 0, 0); 1375 trace_rcu_batch_start(rsp->name, 0, 0);
1376 trace_rcu_batch_end(rsp->name, 0); 1376 trace_rcu_batch_end(rsp->name, 0, !!ACCESS_ONCE(rdp->nxtlist),
1377 need_resched(), is_idle_task(current),
1378 rcu_is_callbacks_kthread());
1377 return; 1379 return;
1378 } 1380 }
1379 1381
@@ -1409,7 +1411,9 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
1409 } 1411 }
1410 1412
1411 local_irq_save(flags); 1413 local_irq_save(flags);
1412 trace_rcu_batch_end(rsp->name, count); 1414 trace_rcu_batch_end(rsp->name, count, !!list, need_resched(),
1415 is_idle_task(current),
1416 rcu_is_callbacks_kthread());
1413 1417
1414 /* Update count, and requeue any remaining callbacks. */ 1418 /* Update count, and requeue any remaining callbacks. */
1415 rdp->qlen -= count; 1419 rdp->qlen -= count;