diff options
| author | Ingo Molnar <mingo@elte.hu> | 2009-09-02 02:20:32 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-09-02 02:20:35 -0400 |
| commit | f14eff1cc2f418a7c5e23aedc6a1bdca3343b871 (patch) | |
| tree | fd8d5f7ed2b2e94eff4007e8da0e9ed205d8d5c9 /include/trace | |
| parent | 84e9dabf6e6a78928c6a1a8ba235c9fb0908d0f8 (diff) | |
| parent | 326ba5010a5429a5a528b268b36a5900d4ab0eba (diff) | |
Merge commit 'v2.6.31-rc8' into sched/core
Merge reason: bump from rc5 to rc8, but also pick up TP_perf_assign()
API, a patch will be queued that depends on it.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/trace')
| -rw-r--r-- | include/trace/ftrace.h | 183 |
1 files changed, 158 insertions, 25 deletions
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 1867553c61e5..f64fbaae781a 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
| @@ -144,6 +144,9 @@ | |||
| 144 | #undef TP_fast_assign | 144 | #undef TP_fast_assign |
| 145 | #define TP_fast_assign(args...) args | 145 | #define TP_fast_assign(args...) args |
| 146 | 146 | ||
| 147 | #undef TP_perf_assign | ||
| 148 | #define TP_perf_assign(args...) | ||
| 149 | |||
| 147 | #undef TRACE_EVENT | 150 | #undef TRACE_EVENT |
| 148 | #define TRACE_EVENT(call, proto, args, tstruct, func, print) \ | 151 | #define TRACE_EVENT(call, proto, args, tstruct, func, print) \ |
| 149 | static int \ | 152 | static int \ |
| @@ -345,6 +348,56 @@ static inline int ftrace_get_offsets_##call( \ | |||
| 345 | 348 | ||
| 346 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | 349 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) |
| 347 | 350 | ||
| 351 | #ifdef CONFIG_EVENT_PROFILE | ||
| 352 | |||
| 353 | /* | ||
| 354 | * Generate the functions needed for tracepoint perf_counter support. | ||
| 355 | * | ||
| 356 | * NOTE: The insertion profile callback (ftrace_profile_<call>) is defined later | ||
| 357 | * | ||
| 358 | * static int ftrace_profile_enable_<call>(struct ftrace_event_call *event_call) | ||
| 359 | * { | ||
| 360 | * int ret = 0; | ||
| 361 | * | ||
| 362 | * if (!atomic_inc_return(&event_call->profile_count)) | ||
| 363 | * ret = register_trace_<call>(ftrace_profile_<call>); | ||
| 364 | * | ||
| 365 | * return ret; | ||
| 366 | * } | ||
| 367 | * | ||
| 368 | * static void ftrace_profile_disable_<call>(struct ftrace_event_call *event_call) | ||
| 369 | * { | ||
| 370 | * if (atomic_add_negative(-1, &event->call->profile_count)) | ||
| 371 | * unregister_trace_<call>(ftrace_profile_<call>); | ||
| 372 | * } | ||
| 373 | * | ||
| 374 | */ | ||
| 375 | |||
| 376 | #undef TRACE_EVENT | ||
| 377 | #define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ | ||
| 378 | \ | ||
| 379 | static void ftrace_profile_##call(proto); \ | ||
| 380 | \ | ||
| 381 | static int ftrace_profile_enable_##call(struct ftrace_event_call *event_call) \ | ||
| 382 | { \ | ||
| 383 | int ret = 0; \ | ||
| 384 | \ | ||
| 385 | if (!atomic_inc_return(&event_call->profile_count)) \ | ||
| 386 | ret = register_trace_##call(ftrace_profile_##call); \ | ||
| 387 | \ | ||
| 388 | return ret; \ | ||
| 389 | } \ | ||
| 390 | \ | ||
| 391 | static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\ | ||
| 392 | { \ | ||
| 393 | if (atomic_add_negative(-1, &event_call->profile_count)) \ | ||
| 394 | unregister_trace_##call(ftrace_profile_##call); \ | ||
| 395 | } | ||
| 396 | |||
| 397 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | ||
| 398 | |||
| 399 | #endif | ||
| 400 | |||
| 348 | /* | 401 | /* |
| 349 | * Stage 4 of the trace events. | 402 | * Stage 4 of the trace events. |
| 350 | * | 403 | * |
| @@ -447,28 +500,6 @@ static inline int ftrace_get_offsets_##call( \ | |||
| 447 | #define TP_FMT(fmt, args...) fmt "\n", ##args | 500 | #define TP_FMT(fmt, args...) fmt "\n", ##args |
| 448 | 501 | ||
| 449 | #ifdef CONFIG_EVENT_PROFILE | 502 | #ifdef CONFIG_EVENT_PROFILE |
| 450 | #define _TRACE_PROFILE(call, proto, args) \ | ||
| 451 | static void ftrace_profile_##call(proto) \ | ||
| 452 | { \ | ||
| 453 | extern void perf_tpcounter_event(int); \ | ||
| 454 | perf_tpcounter_event(event_##call.id); \ | ||
| 455 | } \ | ||
| 456 | \ | ||
| 457 | static int ftrace_profile_enable_##call(struct ftrace_event_call *event_call) \ | ||
| 458 | { \ | ||
| 459 | int ret = 0; \ | ||
| 460 | \ | ||
| 461 | if (!atomic_inc_return(&event_call->profile_count)) \ | ||
| 462 | ret = register_trace_##call(ftrace_profile_##call); \ | ||
| 463 | \ | ||
| 464 | return ret; \ | ||
| 465 | } \ | ||
| 466 | \ | ||
| 467 | static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\ | ||
| 468 | { \ | ||
| 469 | if (atomic_add_negative(-1, &event_call->profile_count)) \ | ||
| 470 | unregister_trace_##call(ftrace_profile_##call); \ | ||
| 471 | } | ||
| 472 | 503 | ||
| 473 | #define _TRACE_PROFILE_INIT(call) \ | 504 | #define _TRACE_PROFILE_INIT(call) \ |
| 474 | .profile_count = ATOMIC_INIT(-1), \ | 505 | .profile_count = ATOMIC_INIT(-1), \ |
| @@ -476,7 +507,6 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\ | |||
| 476 | .profile_disable = ftrace_profile_disable_##call, | 507 | .profile_disable = ftrace_profile_disable_##call, |
| 477 | 508 | ||
| 478 | #else | 509 | #else |
| 479 | #define _TRACE_PROFILE(call, proto, args) | ||
| 480 | #define _TRACE_PROFILE_INIT(call) | 510 | #define _TRACE_PROFILE_INIT(call) |
| 481 | #endif | 511 | #endif |
| 482 | 512 | ||
| @@ -502,7 +532,6 @@ static void ftrace_profile_disable_##call(struct ftrace_event_call *event_call)\ | |||
| 502 | 532 | ||
| 503 | #undef TRACE_EVENT | 533 | #undef TRACE_EVENT |
| 504 | #define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ | 534 | #define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ |
| 505 | _TRACE_PROFILE(call, PARAMS(proto), PARAMS(args)) \ | ||
| 506 | \ | 535 | \ |
| 507 | static struct ftrace_event_call event_##call; \ | 536 | static struct ftrace_event_call event_##call; \ |
| 508 | \ | 537 | \ |
| @@ -586,6 +615,110 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
| 586 | 615 | ||
| 587 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | 616 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) |
| 588 | 617 | ||
| 589 | #undef _TRACE_PROFILE | 618 | /* |
| 619 | * Define the insertion callback to profile events | ||
| 620 | * | ||
| 621 | * The job is very similar to ftrace_raw_event_<call> except that we don't | ||
| 622 | * insert in the ring buffer but in a perf counter. | ||
| 623 | * | ||
| 624 | * static void ftrace_profile_<call>(proto) | ||
| 625 | * { | ||
| 626 | * struct ftrace_data_offsets_<call> __maybe_unused __data_offsets; | ||
| 627 | * struct ftrace_event_call *event_call = &event_<call>; | ||
| 628 | * extern void perf_tpcounter_event(int, u64, u64, void *, int); | ||
| 629 | * struct ftrace_raw_##call *entry; | ||
| 630 | * u64 __addr = 0, __count = 1; | ||
| 631 | * unsigned long irq_flags; | ||
| 632 | * int __entry_size; | ||
| 633 | * int __data_size; | ||
| 634 | * int pc; | ||
| 635 | * | ||
| 636 | * local_save_flags(irq_flags); | ||
| 637 | * pc = preempt_count(); | ||
| 638 | * | ||
| 639 | * __data_size = ftrace_get_offsets_<call>(&__data_offsets, args); | ||
| 640 | * | ||
| 641 | * // Below we want to get the aligned size by taking into account | ||
| 642 | * // the u32 field that will later store the buffer size | ||
| 643 | * __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32), | ||
| 644 | * sizeof(u64)); | ||
| 645 | * __entry_size -= sizeof(u32); | ||
| 646 | * | ||
| 647 | * do { | ||
| 648 | * char raw_data[__entry_size]; <- allocate our sample in the stack | ||
| 649 | * struct trace_entry *ent; | ||
| 650 | * | ||
| 651 | * zero dead bytes from alignment to avoid stack leak to userspace: | ||
| 652 | * | ||
| 653 | * *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; | ||
| 654 | * entry = (struct ftrace_raw_<call> *)raw_data; | ||
| 655 | * ent = &entry->ent; | ||
| 656 | * tracing_generic_entry_update(ent, irq_flags, pc); | ||
| 657 | * ent->type = event_call->id; | ||
| 658 | * | ||
| 659 | * <tstruct> <- do some jobs with dynamic arrays | ||
| 660 | * | ||
| 661 | * <assign> <- affect our values | ||
| 662 | * | ||
| 663 | * perf_tpcounter_event(event_call->id, __addr, __count, entry, | ||
| 664 | * __entry_size); <- submit them to perf counter | ||
| 665 | * } while (0); | ||
| 666 | * | ||
| 667 | * } | ||
| 668 | */ | ||
| 669 | |||
| 670 | #ifdef CONFIG_EVENT_PROFILE | ||
| 671 | |||
| 672 | #undef __perf_addr | ||
| 673 | #define __perf_addr(a) __addr = (a) | ||
| 674 | |||
| 675 | #undef __perf_count | ||
| 676 | #define __perf_count(c) __count = (c) | ||
| 677 | |||
| 678 | #undef TRACE_EVENT | ||
| 679 | #define TRACE_EVENT(call, proto, args, tstruct, assign, print) \ | ||
| 680 | static void ftrace_profile_##call(proto) \ | ||
| 681 | { \ | ||
| 682 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ | ||
| 683 | struct ftrace_event_call *event_call = &event_##call; \ | ||
| 684 | extern void perf_tpcounter_event(int, u64, u64, void *, int); \ | ||
| 685 | struct ftrace_raw_##call *entry; \ | ||
| 686 | u64 __addr = 0, __count = 1; \ | ||
| 687 | unsigned long irq_flags; \ | ||
| 688 | int __entry_size; \ | ||
| 689 | int __data_size; \ | ||
| 690 | int pc; \ | ||
| 691 | \ | ||
| 692 | local_save_flags(irq_flags); \ | ||
| 693 | pc = preempt_count(); \ | ||
| 694 | \ | ||
| 695 | __data_size = ftrace_get_offsets_##call(&__data_offsets, args); \ | ||
| 696 | __entry_size = ALIGN(__data_size + sizeof(*entry) + sizeof(u32),\ | ||
| 697 | sizeof(u64)); \ | ||
| 698 | __entry_size -= sizeof(u32); \ | ||
| 699 | \ | ||
| 700 | do { \ | ||
| 701 | char raw_data[__entry_size]; \ | ||
| 702 | struct trace_entry *ent; \ | ||
| 703 | \ | ||
| 704 | *(u64 *)(&raw_data[__entry_size - sizeof(u64)]) = 0ULL; \ | ||
| 705 | entry = (struct ftrace_raw_##call *)raw_data; \ | ||
| 706 | ent = &entry->ent; \ | ||
| 707 | tracing_generic_entry_update(ent, irq_flags, pc); \ | ||
| 708 | ent->type = event_call->id; \ | ||
| 709 | \ | ||
| 710 | tstruct \ | ||
| 711 | \ | ||
| 712 | { assign; } \ | ||
| 713 | \ | ||
| 714 | perf_tpcounter_event(event_call->id, __addr, __count, entry,\ | ||
| 715 | __entry_size); \ | ||
| 716 | } while (0); \ | ||
| 717 | \ | ||
| 718 | } | ||
| 719 | |||
| 720 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | ||
| 721 | #endif /* CONFIG_EVENT_PROFILE */ | ||
| 722 | |||
| 590 | #undef _TRACE_PROFILE_INIT | 723 | #undef _TRACE_PROFILE_INIT |
| 591 | 724 | ||
