diff options
Diffstat (limited to 'tools/lib/traceevent/event-parse.c')
-rw-r--r-- | tools/lib/traceevent/event-parse.c | 156 |
1 files changed, 123 insertions, 33 deletions
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c index c3bd294a63d1..190cc886ab91 100644 --- a/tools/lib/traceevent/event-parse.c +++ b/tools/lib/traceevent/event-parse.c | |||
@@ -1951,6 +1951,7 @@ process_op(struct event_format *event, struct print_arg *arg, char **tok) | |||
1951 | strcmp(token, "*") == 0 || | 1951 | strcmp(token, "*") == 0 || |
1952 | strcmp(token, "^") == 0 || | 1952 | strcmp(token, "^") == 0 || |
1953 | strcmp(token, "/") == 0 || | 1953 | strcmp(token, "/") == 0 || |
1954 | strcmp(token, "%") == 0 || | ||
1954 | strcmp(token, "<") == 0 || | 1955 | strcmp(token, "<") == 0 || |
1955 | strcmp(token, ">") == 0 || | 1956 | strcmp(token, ">") == 0 || |
1956 | strcmp(token, "<=") == 0 || | 1957 | strcmp(token, "<=") == 0 || |
@@ -2397,6 +2398,12 @@ static int arg_num_eval(struct print_arg *arg, long long *val) | |||
2397 | break; | 2398 | break; |
2398 | *val = left + right; | 2399 | *val = left + right; |
2399 | break; | 2400 | break; |
2401 | case '~': | ||
2402 | ret = arg_num_eval(arg->op.right, &right); | ||
2403 | if (!ret) | ||
2404 | break; | ||
2405 | *val = ~right; | ||
2406 | break; | ||
2400 | default: | 2407 | default: |
2401 | do_warning("unknown op '%s'", arg->op.op); | 2408 | do_warning("unknown op '%s'", arg->op.op); |
2402 | ret = 0; | 2409 | ret = 0; |
@@ -2634,6 +2641,7 @@ process_hex(struct event_format *event, struct print_arg *arg, char **tok) | |||
2634 | 2641 | ||
2635 | free_field: | 2642 | free_field: |
2636 | free_arg(arg->hex.field); | 2643 | free_arg(arg->hex.field); |
2644 | arg->hex.field = NULL; | ||
2637 | out: | 2645 | out: |
2638 | *tok = NULL; | 2646 | *tok = NULL; |
2639 | return EVENT_ERROR; | 2647 | return EVENT_ERROR; |
@@ -2658,8 +2666,10 @@ process_int_array(struct event_format *event, struct print_arg *arg, char **tok) | |||
2658 | 2666 | ||
2659 | free_size: | 2667 | free_size: |
2660 | free_arg(arg->int_array.count); | 2668 | free_arg(arg->int_array.count); |
2669 | arg->int_array.count = NULL; | ||
2661 | free_field: | 2670 | free_field: |
2662 | free_arg(arg->int_array.field); | 2671 | free_arg(arg->int_array.field); |
2672 | arg->int_array.field = NULL; | ||
2663 | out: | 2673 | out: |
2664 | *tok = NULL; | 2674 | *tok = NULL; |
2665 | return EVENT_ERROR; | 2675 | return EVENT_ERROR; |
@@ -3689,6 +3699,9 @@ eval_num_arg(void *data, int size, struct event_format *event, struct print_arg | |||
3689 | case '/': | 3699 | case '/': |
3690 | val = left / right; | 3700 | val = left / right; |
3691 | break; | 3701 | break; |
3702 | case '%': | ||
3703 | val = left % right; | ||
3704 | break; | ||
3692 | case '*': | 3705 | case '*': |
3693 | val = left * right; | 3706 | val = left * right; |
3694 | break; | 3707 | break; |
@@ -4971,7 +4984,7 @@ static void pretty_print(struct trace_seq *s, void *data, int size, struct event | |||
4971 | break; | 4984 | break; |
4972 | } | 4985 | } |
4973 | } | 4986 | } |
4974 | if (pevent->long_size == 8 && ls && | 4987 | if (pevent->long_size == 8 && ls == 1 && |
4975 | sizeof(long) != 8) { | 4988 | sizeof(long) != 8) { |
4976 | char *p; | 4989 | char *p; |
4977 | 4990 | ||
@@ -5335,41 +5348,45 @@ static bool is_timestamp_in_us(char *trace_clock, bool use_trace_clock) | |||
5335 | return false; | 5348 | return false; |
5336 | } | 5349 | } |
5337 | 5350 | ||
5338 | void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | 5351 | /** |
5339 | struct pevent_record *record, bool use_trace_clock) | 5352 | * pevent_find_event_by_record - return the event from a given record |
5353 | * @pevent: a handle to the pevent | ||
5354 | * @record: The record to get the event from | ||
5355 | * | ||
5356 | * Returns the associated event for a given record, or NULL if non is | ||
5357 | * is found. | ||
5358 | */ | ||
5359 | struct event_format * | ||
5360 | pevent_find_event_by_record(struct pevent *pevent, struct pevent_record *record) | ||
5340 | { | 5361 | { |
5341 | static const char *spaces = " "; /* 20 spaces */ | ||
5342 | struct event_format *event; | ||
5343 | unsigned long secs; | ||
5344 | unsigned long usecs; | ||
5345 | unsigned long nsecs; | ||
5346 | const char *comm; | ||
5347 | void *data = record->data; | ||
5348 | int type; | 5362 | int type; |
5349 | int pid; | ||
5350 | int len; | ||
5351 | int p; | ||
5352 | bool use_usec_format; | ||
5353 | |||
5354 | use_usec_format = is_timestamp_in_us(pevent->trace_clock, | ||
5355 | use_trace_clock); | ||
5356 | if (use_usec_format) { | ||
5357 | secs = record->ts / NSECS_PER_SEC; | ||
5358 | nsecs = record->ts - secs * NSECS_PER_SEC; | ||
5359 | } | ||
5360 | 5363 | ||
5361 | if (record->size < 0) { | 5364 | if (record->size < 0) { |
5362 | do_warning("ug! negative record size %d", record->size); | 5365 | do_warning("ug! negative record size %d", record->size); |
5363 | return; | 5366 | return NULL; |
5364 | } | 5367 | } |
5365 | 5368 | ||
5366 | type = trace_parse_common_type(pevent, data); | 5369 | type = trace_parse_common_type(pevent, record->data); |
5367 | 5370 | ||
5368 | event = pevent_find_event(pevent, type); | 5371 | return pevent_find_event(pevent, type); |
5369 | if (!event) { | 5372 | } |
5370 | do_warning("ug! no event found for type %d", type); | 5373 | |
5371 | return; | 5374 | /** |
5372 | } | 5375 | * pevent_print_event_task - Write the event task comm, pid and CPU |
5376 | * @pevent: a handle to the pevent | ||
5377 | * @s: the trace_seq to write to | ||
5378 | * @event: the handle to the record's event | ||
5379 | * @record: The record to get the event from | ||
5380 | * | ||
5381 | * Writes the tasks comm, pid and CPU to @s. | ||
5382 | */ | ||
5383 | void pevent_print_event_task(struct pevent *pevent, struct trace_seq *s, | ||
5384 | struct event_format *event, | ||
5385 | struct pevent_record *record) | ||
5386 | { | ||
5387 | void *data = record->data; | ||
5388 | const char *comm; | ||
5389 | int pid; | ||
5373 | 5390 | ||
5374 | pid = parse_common_pid(pevent, data); | 5391 | pid = parse_common_pid(pevent, data); |
5375 | comm = find_cmdline(pevent, pid); | 5392 | comm = find_cmdline(pevent, pid); |
@@ -5377,9 +5394,43 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | |||
5377 | if (pevent->latency_format) { | 5394 | if (pevent->latency_format) { |
5378 | trace_seq_printf(s, "%8.8s-%-5d %3d", | 5395 | trace_seq_printf(s, "%8.8s-%-5d %3d", |
5379 | comm, pid, record->cpu); | 5396 | comm, pid, record->cpu); |
5380 | pevent_data_lat_fmt(pevent, s, record); | ||
5381 | } else | 5397 | } else |
5382 | trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu); | 5398 | trace_seq_printf(s, "%16s-%-5d [%03d]", comm, pid, record->cpu); |
5399 | } | ||
5400 | |||
5401 | /** | ||
5402 | * pevent_print_event_time - Write the event timestamp | ||
5403 | * @pevent: a handle to the pevent | ||
5404 | * @s: the trace_seq to write to | ||
5405 | * @event: the handle to the record's event | ||
5406 | * @record: The record to get the event from | ||
5407 | * @use_trace_clock: Set to parse according to the @pevent->trace_clock | ||
5408 | * | ||
5409 | * Writes the timestamp of the record into @s. | ||
5410 | */ | ||
5411 | void pevent_print_event_time(struct pevent *pevent, struct trace_seq *s, | ||
5412 | struct event_format *event, | ||
5413 | struct pevent_record *record, | ||
5414 | bool use_trace_clock) | ||
5415 | { | ||
5416 | unsigned long secs; | ||
5417 | unsigned long usecs; | ||
5418 | unsigned long nsecs; | ||
5419 | int p; | ||
5420 | bool use_usec_format; | ||
5421 | |||
5422 | use_usec_format = is_timestamp_in_us(pevent->trace_clock, | ||
5423 | use_trace_clock); | ||
5424 | if (use_usec_format) { | ||
5425 | secs = record->ts / NSECS_PER_SEC; | ||
5426 | nsecs = record->ts - secs * NSECS_PER_SEC; | ||
5427 | } | ||
5428 | |||
5429 | if (pevent->latency_format) { | ||
5430 | trace_seq_printf(s, " %3d", record->cpu); | ||
5431 | pevent_data_lat_fmt(pevent, s, record); | ||
5432 | } else | ||
5433 | trace_seq_printf(s, " [%03d]", record->cpu); | ||
5383 | 5434 | ||
5384 | if (use_usec_format) { | 5435 | if (use_usec_format) { |
5385 | if (pevent->flags & PEVENT_NSEC_OUTPUT) { | 5436 | if (pevent->flags & PEVENT_NSEC_OUTPUT) { |
@@ -5387,14 +5438,36 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | |||
5387 | p = 9; | 5438 | p = 9; |
5388 | } else { | 5439 | } else { |
5389 | usecs = (nsecs + 500) / NSECS_PER_USEC; | 5440 | usecs = (nsecs + 500) / NSECS_PER_USEC; |
5441 | /* To avoid usecs larger than 1 sec */ | ||
5442 | if (usecs >= 1000000) { | ||
5443 | usecs -= 1000000; | ||
5444 | secs++; | ||
5445 | } | ||
5390 | p = 6; | 5446 | p = 6; |
5391 | } | 5447 | } |
5392 | 5448 | ||
5393 | trace_seq_printf(s, " %5lu.%0*lu: %s: ", | 5449 | trace_seq_printf(s, " %5lu.%0*lu:", secs, p, usecs); |
5394 | secs, p, usecs, event->name); | ||
5395 | } else | 5450 | } else |
5396 | trace_seq_printf(s, " %12llu: %s: ", | 5451 | trace_seq_printf(s, " %12llu:", record->ts); |
5397 | record->ts, event->name); | 5452 | } |
5453 | |||
5454 | /** | ||
5455 | * pevent_print_event_data - Write the event data section | ||
5456 | * @pevent: a handle to the pevent | ||
5457 | * @s: the trace_seq to write to | ||
5458 | * @event: the handle to the record's event | ||
5459 | * @record: The record to get the event from | ||
5460 | * | ||
5461 | * Writes the parsing of the record's data to @s. | ||
5462 | */ | ||
5463 | void pevent_print_event_data(struct pevent *pevent, struct trace_seq *s, | ||
5464 | struct event_format *event, | ||
5465 | struct pevent_record *record) | ||
5466 | { | ||
5467 | static const char *spaces = " "; /* 20 spaces */ | ||
5468 | int len; | ||
5469 | |||
5470 | trace_seq_printf(s, " %s: ", event->name); | ||
5398 | 5471 | ||
5399 | /* Space out the event names evenly. */ | 5472 | /* Space out the event names evenly. */ |
5400 | len = strlen(event->name); | 5473 | len = strlen(event->name); |
@@ -5404,6 +5477,23 @@ void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | |||
5404 | pevent_event_info(s, event, record); | 5477 | pevent_event_info(s, event, record); |
5405 | } | 5478 | } |
5406 | 5479 | ||
5480 | void pevent_print_event(struct pevent *pevent, struct trace_seq *s, | ||
5481 | struct pevent_record *record, bool use_trace_clock) | ||
5482 | { | ||
5483 | struct event_format *event; | ||
5484 | |||
5485 | event = pevent_find_event_by_record(pevent, record); | ||
5486 | if (!event) { | ||
5487 | do_warning("ug! no event found for type %d", | ||
5488 | trace_parse_common_type(pevent, record->data)); | ||
5489 | return; | ||
5490 | } | ||
5491 | |||
5492 | pevent_print_event_task(pevent, s, event, record); | ||
5493 | pevent_print_event_time(pevent, s, event, record, use_trace_clock); | ||
5494 | pevent_print_event_data(pevent, s, event, record); | ||
5495 | } | ||
5496 | |||
5407 | static int events_id_cmp(const void *a, const void *b) | 5497 | static int events_id_cmp(const void *a, const void *b) |
5408 | { | 5498 | { |
5409 | struct event_format * const * ea = a; | 5499 | struct event_format * const * ea = a; |