diff options
author | Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> | 2008-11-14 17:47:39 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-11-16 03:01:29 -0500 |
commit | c1df1bd2c4d4b20c83755a0f41956b57aec4842a (patch) | |
tree | 08761333b0850c6acfb31d72d7777dccc135ebde /kernel/marker.c | |
parent | a419246ac7c2d9282dfd843103702895bb3f3fd7 (diff) |
markers: auto enable tracepoints (new API : trace_mark_tp())
Impact: new API
Add a new API trace_mark_tp(), which declares a marker within a
tracepoint probe. When the marker is activated, the tracepoint is
automatically enabled.
No branch test is used at the marker site, because it would be a
duplicate of the branch already present in the tracepoint.
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/marker.c')
-rw-r--r-- | kernel/marker.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/kernel/marker.c b/kernel/marker.c index 348e70cc355a..c14ec26a9b9f 100644 --- a/kernel/marker.c +++ b/kernel/marker.c | |||
@@ -479,7 +479,7 @@ static int marker_set_format(struct marker_entry *entry, const char *format) | |||
479 | static int set_marker(struct marker_entry *entry, struct marker *elem, | 479 | static int set_marker(struct marker_entry *entry, struct marker *elem, |
480 | int active) | 480 | int active) |
481 | { | 481 | { |
482 | int ret; | 482 | int ret = 0; |
483 | WARN_ON(strcmp(entry->name, elem->name) != 0); | 483 | WARN_ON(strcmp(entry->name, elem->name) != 0); |
484 | 484 | ||
485 | if (entry->format) { | 485 | if (entry->format) { |
@@ -531,9 +531,40 @@ static int set_marker(struct marker_entry *entry, struct marker *elem, | |||
531 | */ | 531 | */ |
532 | smp_wmb(); | 532 | smp_wmb(); |
533 | elem->ptype = entry->ptype; | 533 | elem->ptype = entry->ptype; |
534 | |||
535 | if (elem->tp_name && (active ^ elem->state)) { | ||
536 | WARN_ON(!elem->tp_cb); | ||
537 | /* | ||
538 | * It is ok to directly call the probe registration because type | ||
539 | * checking has been done in the __trace_mark_tp() macro. | ||
540 | */ | ||
541 | |||
542 | if (active) { | ||
543 | /* | ||
544 | * try_module_get should always succeed because we hold | ||
545 | * lock_module() to get the tp_cb address. | ||
546 | */ | ||
547 | ret = try_module_get(__module_text_address( | ||
548 | (unsigned long)elem->tp_cb)); | ||
549 | BUG_ON(!ret); | ||
550 | ret = tracepoint_probe_register_noupdate( | ||
551 | elem->tp_name, | ||
552 | elem->tp_cb); | ||
553 | } else { | ||
554 | ret = tracepoint_probe_unregister_noupdate( | ||
555 | elem->tp_name, | ||
556 | elem->tp_cb); | ||
557 | /* | ||
558 | * tracepoint_probe_update_all() must be called | ||
559 | * before the module containing tp_cb is unloaded. | ||
560 | */ | ||
561 | module_put(__module_text_address( | ||
562 | (unsigned long)elem->tp_cb)); | ||
563 | } | ||
564 | } | ||
534 | elem->state = active; | 565 | elem->state = active; |
535 | 566 | ||
536 | return 0; | 567 | return ret; |
537 | } | 568 | } |
538 | 569 | ||
539 | /* | 570 | /* |
@@ -544,7 +575,24 @@ static int set_marker(struct marker_entry *entry, struct marker *elem, | |||
544 | */ | 575 | */ |
545 | static void disable_marker(struct marker *elem) | 576 | static void disable_marker(struct marker *elem) |
546 | { | 577 | { |
578 | int ret; | ||
579 | |||
547 | /* leave "call" as is. It is known statically. */ | 580 | /* leave "call" as is. It is known statically. */ |
581 | if (elem->tp_name && elem->state) { | ||
582 | WARN_ON(!elem->tp_cb); | ||
583 | /* | ||
584 | * It is ok to directly call the probe registration because type | ||
585 | * checking has been done in the __trace_mark_tp() macro. | ||
586 | */ | ||
587 | ret = tracepoint_probe_unregister_noupdate(elem->tp_name, | ||
588 | elem->tp_cb); | ||
589 | WARN_ON(ret); | ||
590 | /* | ||
591 | * tracepoint_probe_update_all() must be called | ||
592 | * before the module containing tp_cb is unloaded. | ||
593 | */ | ||
594 | module_put(__module_text_address((unsigned long)elem->tp_cb)); | ||
595 | } | ||
548 | elem->state = 0; | 596 | elem->state = 0; |
549 | elem->single.func = __mark_empty_function; | 597 | elem->single.func = __mark_empty_function; |
550 | /* Update the function before setting the ptype */ | 598 | /* Update the function before setting the ptype */ |
@@ -608,6 +656,7 @@ static void marker_update_probes(void) | |||
608 | marker_update_probe_range(__start___markers, __stop___markers); | 656 | marker_update_probe_range(__start___markers, __stop___markers); |
609 | /* Markers in modules. */ | 657 | /* Markers in modules. */ |
610 | module_update_markers(); | 658 | module_update_markers(); |
659 | tracepoint_probe_update_all(); | ||
611 | } | 660 | } |
612 | 661 | ||
613 | /** | 662 | /** |