aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2014-06-02 23:20:16 -0400
committerJiri Olsa <jolsa@kernel.org>2014-06-07 17:33:37 -0400
commit473a778a2f2949972b52ad7fc61577f381f2d05e (patch)
tree17cbf62b89bcbc38b600027cc61eda50469a796b /tools
parent49440828ad7b809e9d31f6108875e3b1e974690c (diff)
tools lib traceevent: Added support for __get_bitmask() macro
Coming in v3.16, trace events will be able to save bitmasks in raw format in the ring buffer and output it with the __get_bitmask() macro. In order for userspace tools to parse this, it must be able to handle the __get_bitmask() call and be able to convert the data that's in the ring buffer into a nice bitmask format. The output is similar to what the kernel uses to print bitmasks, with a comma separator every 4 bytes (8 characters). This allows for cpumasks to also be saved efficiently. The first user is the thermal:thermal_power_limit event which has the following output: thermal_power_limit: cpus=0000000f freq=1900000 cdev_state=0 power=5252 Link: http://lkml.kernel.org/r/20140506132238.22e136d1@gandalf.local.home Suggested-by: Javi Merino <javi.merino@arm.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Acked-by: Namhyung Kim <namhyung@kernel.org> Tested-by: Javi Merino <javi.merino@arm.com> Link: http://lkml.kernel.org/r/20140603032224.229186537@goodmis.org Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/traceevent/event-parse.c113
-rw-r--r--tools/lib/traceevent/event-parse.h7
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c1
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c1
4 files changed, 122 insertions, 0 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index b83184f2d484..93825a17dcce 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -765,6 +765,9 @@ static void free_arg(struct print_arg *arg)
765 case PRINT_BSTRING: 765 case PRINT_BSTRING:
766 free(arg->string.string); 766 free(arg->string.string);
767 break; 767 break;
768 case PRINT_BITMASK:
769 free(arg->bitmask.bitmask);
770 break;
768 case PRINT_DYNAMIC_ARRAY: 771 case PRINT_DYNAMIC_ARRAY:
769 free(arg->dynarray.index); 772 free(arg->dynarray.index);
770 break; 773 break;
@@ -2268,6 +2271,7 @@ static int arg_num_eval(struct print_arg *arg, long long *val)
2268 case PRINT_FIELD ... PRINT_SYMBOL: 2271 case PRINT_FIELD ... PRINT_SYMBOL:
2269 case PRINT_STRING: 2272 case PRINT_STRING:
2270 case PRINT_BSTRING: 2273 case PRINT_BSTRING:
2274 case PRINT_BITMASK:
2271 default: 2275 default:
2272 do_warning("invalid eval type %d", arg->type); 2276 do_warning("invalid eval type %d", arg->type);
2273 ret = 0; 2277 ret = 0;
@@ -2296,6 +2300,7 @@ static char *arg_eval (struct print_arg *arg)
2296 case PRINT_FIELD ... PRINT_SYMBOL: 2300 case PRINT_FIELD ... PRINT_SYMBOL:
2297 case PRINT_STRING: 2301 case PRINT_STRING:
2298 case PRINT_BSTRING: 2302 case PRINT_BSTRING:
2303 case PRINT_BITMASK:
2299 default: 2304 default:
2300 do_warning("invalid eval type %d", arg->type); 2305 do_warning("invalid eval type %d", arg->type);
2301 break; 2306 break;
@@ -2683,6 +2688,35 @@ process_str(struct event_format *event __maybe_unused, struct print_arg *arg,
2683 return EVENT_ERROR; 2688 return EVENT_ERROR;
2684} 2689}
2685 2690
2691static enum event_type
2692process_bitmask(struct event_format *event __maybe_unused, struct print_arg *arg,
2693 char **tok)
2694{
2695 enum event_type type;
2696 char *token;
2697
2698 if (read_expect_type(EVENT_ITEM, &token) < 0)
2699 goto out_free;
2700
2701 arg->type = PRINT_BITMASK;
2702 arg->bitmask.bitmask = token;
2703 arg->bitmask.offset = -1;
2704
2705 if (read_expected(EVENT_DELIM, ")") < 0)
2706 goto out_err;
2707
2708 type = read_token(&token);
2709 *tok = token;
2710
2711 return type;
2712
2713 out_free:
2714 free_token(token);
2715 out_err:
2716 *tok = NULL;
2717 return EVENT_ERROR;
2718}
2719
2686static struct pevent_function_handler * 2720static struct pevent_function_handler *
2687find_func_handler(struct pevent *pevent, char *func_name) 2721find_func_handler(struct pevent *pevent, char *func_name)
2688{ 2722{
@@ -2797,6 +2831,10 @@ process_function(struct event_format *event, struct print_arg *arg,
2797 free_token(token); 2831 free_token(token);
2798 return process_str(event, arg, tok); 2832 return process_str(event, arg, tok);
2799 } 2833 }
2834 if (strcmp(token, "__get_bitmask") == 0) {
2835 free_token(token);
2836 return process_bitmask(event, arg, tok);
2837 }
2800 if (strcmp(token, "__get_dynamic_array") == 0) { 2838 if (strcmp(token, "__get_dynamic_array") == 0) {
2801 free_token(token); 2839 free_token(token);
2802 return process_dynamic_array(event, arg, tok); 2840 return process_dynamic_array(event, arg, tok);
@@ -3324,6 +3362,7 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg
3324 return eval_type(val, arg, 0); 3362 return eval_type(val, arg, 0);
3325 case PRINT_STRING: 3363 case PRINT_STRING:
3326 case PRINT_BSTRING: 3364 case PRINT_BSTRING:
3365 case PRINT_BITMASK:
3327 return 0; 3366 return 0;
3328 case PRINT_FUNC: { 3367 case PRINT_FUNC: {
3329 struct trace_seq s; 3368 struct trace_seq s;
@@ -3556,6 +3595,60 @@ static void print_str_to_seq(struct trace_seq *s, const char *format,
3556 trace_seq_printf(s, format, str); 3595 trace_seq_printf(s, format, str);
3557} 3596}
3558 3597
3598static void print_bitmask_to_seq(struct pevent *pevent,
3599 struct trace_seq *s, const char *format,
3600 int len_arg, const void *data, int size)
3601{
3602 int nr_bits = size * 8;
3603 int str_size = (nr_bits + 3) / 4;
3604 int len = 0;
3605 char buf[3];
3606 char *str;
3607 int index;
3608 int i;
3609
3610 /*
3611 * The kernel likes to put in commas every 32 bits, we
3612 * can do the same.
3613 */
3614 str_size += (nr_bits - 1) / 32;
3615
3616 str = malloc(str_size + 1);
3617 if (!str) {
3618 do_warning("%s: not enough memory!", __func__);
3619 return;
3620 }
3621 str[str_size] = 0;
3622
3623 /* Start out with -2 for the two chars per byte */
3624 for (i = str_size - 2; i >= 0; i -= 2) {
3625 /*
3626 * data points to a bit mask of size bytes.
3627 * In the kernel, this is an array of long words, thus
3628 * endianess is very important.
3629 */
3630 if (pevent->file_bigendian)
3631 index = size - (len + 1);
3632 else
3633 index = len;
3634
3635 snprintf(buf, 3, "%02x", *((unsigned char *)data + index));
3636 memcpy(str + i, buf, 2);
3637 len++;
3638 if (!(len & 3) && i > 0) {
3639 i--;
3640 str[i] = ',';
3641 }
3642 }
3643
3644 if (len_arg >= 0)
3645 trace_seq_printf(s, format, len_arg, str);
3646 else
3647 trace_seq_printf(s, format, str);
3648
3649 free(str);
3650}
3651
3559static void print_str_arg(struct trace_seq *s, void *data, int size, 3652static void print_str_arg(struct trace_seq *s, void *data, int size,
3560 struct event_format *event, const char *format, 3653 struct event_format *event, const char *format,
3561 int len_arg, struct print_arg *arg) 3654 int len_arg, struct print_arg *arg)
@@ -3691,6 +3784,23 @@ static void print_str_arg(struct trace_seq *s, void *data, int size,
3691 case PRINT_BSTRING: 3784 case PRINT_BSTRING:
3692 print_str_to_seq(s, format, len_arg, arg->string.string); 3785 print_str_to_seq(s, format, len_arg, arg->string.string);
3693 break; 3786 break;
3787 case PRINT_BITMASK: {
3788 int bitmask_offset;
3789 int bitmask_size;
3790
3791 if (arg->bitmask.offset == -1) {
3792 struct format_field *f;
3793
3794 f = pevent_find_any_field(event, arg->bitmask.bitmask);
3795 arg->bitmask.offset = f->offset;
3796 }
3797 bitmask_offset = data2host4(pevent, data + arg->bitmask.offset);
3798 bitmask_size = bitmask_offset >> 16;
3799 bitmask_offset &= 0xffff;