diff options
author | Paul E. McKenney <paul.mckenney@linaro.org> | 2012-01-06 17:11:30 -0500 |
---|---|---|
committer | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2012-02-21 12:03:25 -0500 |
commit | 486e259340fc4c60474f2c14703e3b3634bb58ca (patch) | |
tree | 70a58702194588fa0773463523f72c682785d040 /include/trace | |
parent | 0bb7b59d6e2b8440cd7097097dd4bbfc4d76ed07 (diff) |
rcu: Avoid waking up CPUs having only kfree_rcu() callbacks
When CONFIG_RCU_FAST_NO_HZ is enabled, RCU will allow a given CPU to
enter dyntick-idle mode even if it still has RCU callbacks queued.
RCU avoids system hangs in this case by scheduling a timer for several
jiffies in the future. However, if all of the callbacks on that CPU
are from kfree_rcu(), there is no reason to wake the CPU up, as it is
not a problem to defer freeing of memory.
This commit therefore tracks the number of callbacks on a given CPU
that are from kfree_rcu(), and avoids scheduling the timer if all of
a given CPU's callbacks are from kfree_rcu().
Signed-off-by: Paul E. McKenney <paul.mckenney@linaro.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Diffstat (limited to 'include/trace')
-rw-r--r-- | include/trace/events/rcu.h | 63 |
1 files changed, 39 insertions, 24 deletions
diff --git a/include/trace/events/rcu.h b/include/trace/events/rcu.h index d2d88bed891b..337099783f37 100644 --- a/include/trace/events/rcu.h +++ b/include/trace/events/rcu.h | |||
@@ -313,19 +313,22 @@ TRACE_EVENT(rcu_prep_idle, | |||
313 | /* | 313 | /* |
314 | * Tracepoint for the registration of a single RCU callback function. | 314 | * Tracepoint for the registration of a single RCU callback function. |
315 | * The first argument is the type of RCU, the second argument is | 315 | * The first argument is the type of RCU, the second argument is |
316 | * a pointer to the RCU callback itself, and the third element is the | 316 | * a pointer to the RCU callback itself, the third element is the |
317 | * new RCU callback queue length for the current CPU. | 317 | * number of lazy callbacks queued, and the fourth element is the |
318 | * total number of callbacks queued. | ||
318 | */ | 319 | */ |
319 | TRACE_EVENT(rcu_callback, | 320 | TRACE_EVENT(rcu_callback, |
320 | 321 | ||
321 | TP_PROTO(char *rcuname, struct rcu_head *rhp, long qlen), | 322 | TP_PROTO(char *rcuname, struct rcu_head *rhp, long qlen_lazy, |
323 | long qlen), | ||
322 | 324 | ||
323 | TP_ARGS(rcuname, rhp, qlen), | 325 | TP_ARGS(rcuname, rhp, qlen_lazy, qlen), |
324 | 326 | ||
325 | TP_STRUCT__entry( | 327 | TP_STRUCT__entry( |
326 | __field(char *, rcuname) | 328 | __field(char *, rcuname) |
327 | __field(void *, rhp) | 329 | __field(void *, rhp) |
328 | __field(void *, func) | 330 | __field(void *, func) |
331 | __field(long, qlen_lazy) | ||
329 | __field(long, qlen) | 332 | __field(long, qlen) |
330 | ), | 333 | ), |
331 | 334 | ||
@@ -333,11 +336,13 @@ TRACE_EVENT(rcu_callback, | |||
333 | __entry->rcuname = rcuname; | 336 | __entry->rcuname = rcuname; |
334 | __entry->rhp = rhp; | 337 | __entry->rhp = rhp; |
335 | __entry->func = rhp->func; | 338 | __entry->func = rhp->func; |
339 | __entry->qlen_lazy = qlen_lazy; | ||
336 | __entry->qlen = qlen; | 340 | __entry->qlen = qlen; |
337 | ), | 341 | ), |
338 | 342 | ||
339 | TP_printk("%s rhp=%p func=%pf %ld", | 343 | TP_printk("%s rhp=%p func=%pf %ld/%ld", |
340 | __entry->rcuname, __entry->rhp, __entry->func, __entry->qlen) | 344 | __entry->rcuname, __entry->rhp, __entry->func, |
345 | __entry->qlen_lazy, __entry->qlen) | ||
341 | ); | 346 | ); |
342 | 347 | ||
343 | /* | 348 | /* |
@@ -345,20 +350,21 @@ TRACE_EVENT(rcu_callback, | |||
345 | * kfree() form. The first argument is the RCU type, the second argument | 350 | * kfree() form. The first argument is the RCU type, the second argument |
346 | * is a pointer to the RCU callback, the third argument is the offset | 351 | * is a pointer to the RCU callback, the third argument is the offset |
347 | * of the callback within the enclosing RCU-protected data structure, | 352 | * of the callback within the enclosing RCU-protected data structure, |
348 | * and the fourth argument is the new RCU callback queue length for the | 353 | * the fourth argument is the number of lazy callbacks queued, and the |
349 | * current CPU. | 354 | * fifth argument is the total number of callbacks queued. |
350 | */ | 355 | */ |
351 | TRACE_EVENT(rcu_kfree_callback, | 356 | TRACE_EVENT(rcu_kfree_callback, |
352 | 357 | ||
353 | TP_PROTO(char *rcuname, struct rcu_head *rhp, unsigned long offset, | 358 | TP_PROTO(char *rcuname, struct rcu_head *rhp, unsigned long offset, |
354 | long qlen), | 359 | long qlen_lazy, long qlen), |
355 | 360 | ||
356 | TP_ARGS(rcuname, rhp, offset, qlen), | 361 | TP_ARGS(rcuname, rhp, offset, qlen_lazy, qlen), |
357 | 362 | ||
358 | TP_STRUCT__entry( | 363 | TP_STRUCT__entry( |
359 | __field(char *, rcuname) | 364 | __field(char *, rcuname) |
360 | __field(void *, rhp) | 365 | __field(void *, rhp) |
361 | __field(unsigned long, offset) | 366 | __field(unsigned long, offset) |
367 | __field(long, qlen_lazy) | ||
362 | __field(long, qlen) | 368 | __field(long, qlen) |
363 | ), | 369 | ), |
364 | 370 | ||
@@ -366,41 +372,45 @@ TRACE_EVENT(rcu_kfree_callback, | |||
366 | __entry->rcuname = rcuname; | 372 | __entry->rcuname = rcuname; |
367 | __entry->rhp = rhp; | 373 | __entry->rhp = rhp; |
368 | __entry->offset = offset; | 374 | __entry->offset = offset; |
375 | __entry->qlen_lazy = qlen_lazy; | ||
369 | __entry->qlen = qlen; | 376 | __entry->qlen = qlen; |
370 | ), | 377 | ), |
371 | 378 | ||
372 | TP_printk("%s rhp=%p func=%ld %ld", | 379 | TP_printk("%s rhp=%p func=%ld %ld/%ld", |
373 | __entry->rcuname, __entry->rhp, __entry->offset, | 380 | __entry->rcuname, __entry->rhp, __entry->offset, |
374 | __entry->qlen) | 381 | __entry->qlen_lazy, __entry->qlen) |
375 | ); | 382 | ); |
376 | 383 | ||
377 | /* | 384 | /* |
378 | * Tracepoint for marking the beginning rcu_do_batch, performed to start | 385 | * Tracepoint for marking the beginning rcu_do_batch, performed to start |
379 | * RCU callback invocation. The first argument is the RCU flavor, | 386 | * RCU callback invocation. The first argument is the RCU flavor, |
380 | * the second is the total number of callbacks (including those that | 387 | * the second is the number of lazy callbacks queued, the third is |
381 | * are not yet ready to be invoked), and the third argument is the | 388 | * the total number of callbacks queued, and the fourth argument is |
382 | * current RCU-callback batch limit. | 389 | * the current RCU-callback batch limit. |
383 | */ | 390 | */ |
384 | TRACE_EVENT(rcu_batch_start, | 391 | TRACE_EVENT(rcu_batch_start, |
385 | 392 | ||
386 | TP_PROTO(char *rcuname, long qlen, int blimit), | 393 | TP_PROTO(char *rcuname, long qlen_lazy, long qlen, int blimit), |
387 | 394 | ||
388 | TP_ARGS(rcuname, qlen, blimit), | 395 | TP_ARGS(rcuname, qlen_lazy, qlen, blimit), |
389 | 396 | ||
390 | TP_STRUCT__entry( | 397 | TP_STRUCT__entry( |
391 | __field(char *, rcuname) | 398 | __field(char *, rcuname) |
399 | __field(long, qlen_lazy) | ||
392 | __field(long, qlen) | 400 | __field(long, qlen) |
393 | __field(int, blimit) | 401 | __field(int, blimit) |
394 | ), | 402 | ), |
395 | 403 | ||
396 | TP_fast_assign( | 404 | TP_fast_assign( |
397 | __entry->rcuname = rcuname; | 405 | __entry->rcuname = rcuname; |
406 | __entry->qlen_lazy = qlen_lazy; | ||
398 | __entry->qlen = qlen; | 407 | __entry->qlen = qlen; |
399 | __entry->blimit = blimit; | 408 | __entry->blimit = blimit; |
400 | ), | 409 | ), |
401 | 410 | ||
402 | TP_printk("%s CBs=%ld bl=%d", | 411 | TP_printk("%s CBs=%ld/%ld bl=%d", |
403 | __entry->rcuname, __entry->qlen, __entry->blimit) | 412 | __entry->rcuname, __entry->qlen_lazy, __entry->qlen, |
413 | __entry->blimit) | ||
404 | ); | 414 | ); |
405 | 415 | ||
406 | /* | 416 | /* |
@@ -531,16 +541,21 @@ TRACE_EVENT(rcu_torture_read, | |||
531 | #else /* #ifdef CONFIG_RCU_TRACE */ | 541 | #else /* #ifdef CONFIG_RCU_TRACE */ |
532 | 542 | ||
533 | #define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0) | 543 | #define trace_rcu_grace_period(rcuname, gpnum, gpevent) do { } while (0) |
534 | #define trace_rcu_grace_period_init(rcuname, gpnum, level, grplo, grphi, qsmask) do { } while (0) | 544 | #define trace_rcu_grace_period_init(rcuname, gpnum, level, grplo, grphi, \ |
545 | qsmask) do { } while (0) | ||
535 | #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0) | 546 | #define trace_rcu_preempt_task(rcuname, pid, gpnum) do { } while (0) |
536 | #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0) | 547 | #define trace_rcu_unlock_preempted_task(rcuname, gpnum, pid) do { } while (0) |
537 | #define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, grplo, grphi, gp_tasks) do { } while (0) | 548 | #define trace_rcu_quiescent_state_report(rcuname, gpnum, mask, qsmask, level, \ |
549 | grplo, grphi, gp_tasks) do { } \ | ||
550 | while (0) | ||
538 | #define trace_rcu_fqs(rcuname, gpnum, cpu, qsevent) do { } while (0) | 551 | #define trace_rcu_fqs(rcuname, gpnum, cpu, qsevent) do { } while (0) |
539 | #define trace_rcu_dyntick(polarity, oldnesting, newnesting) do { } while (0) | 552 | #define trace_rcu_dyntick(polarity, oldnesting, newnesting) do { } while (0) |
540 | #define trace_rcu_prep_idle(reason) do { } while (0) | 553 | #define trace_rcu_prep_idle(reason) do { } while (0) |
541 | #define trace_rcu_callback(rcuname, rhp, qlen) do { } while (0) | 554 | #define trace_rcu_callback(rcuname, rhp, qlen_lazy, qlen) do { } while (0) |
542 | #define trace_rcu_kfree_callback(rcuname, rhp, offset, qlen) do { } while (0) | 555 | #define trace_rcu_kfree_callback(rcuname, rhp, offset, qlen_lazy, qlen) \ |
543 | #define trace_rcu_batch_start(rcuname, qlen, blimit) do { } while (0) | 556 | do { } while (0) |
557 | #define trace_rcu_batch_start(rcuname, qlen_lazy, qlen, blimit) \ | ||
558 | do { } while (0) | ||
544 | #define trace_rcu_invoke_callback(rcuname, rhp) do { } while (0) | 559 | #define trace_rcu_invoke_callback(rcuname, rhp) do { } while (0) |
545 | #define trace_rcu_invoke_kfree_callback(rcuname, rhp, offset) do { } while (0) | 560 | #define trace_rcu_invoke_kfree_callback(rcuname, rhp, offset) do { } while (0) |
546 | #define trace_rcu_batch_end(rcuname, callbacks_invoked, cb, nr, iit, risk) \ | 561 | #define trace_rcu_batch_end(rcuname, callbacks_invoked, cb, nr, iit, risk) \ |