| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * CTF writing support via babeltrace. |
|---|
| 3 | 4 | * |
|---|
| 4 | 5 | * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com> |
|---|
| 5 | 6 | * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de> |
|---|
| 6 | | - * |
|---|
| 7 | | - * Released under the GPL v2. (and only v2, not any later version) |
|---|
| 8 | 7 | */ |
|---|
| 9 | 8 | |
|---|
| 10 | 9 | #include <errno.h> |
|---|
| 11 | 10 | #include <inttypes.h> |
|---|
| 12 | 11 | #include <linux/compiler.h> |
|---|
| 13 | 12 | #include <linux/kernel.h> |
|---|
| 13 | +#include <linux/zalloc.h> |
|---|
| 14 | 14 | #include <babeltrace/ctf-writer/writer.h> |
|---|
| 15 | 15 | #include <babeltrace/ctf-writer/clock.h> |
|---|
| 16 | 16 | #include <babeltrace/ctf-writer/stream.h> |
|---|
| .. | .. |
|---|
| 23 | 23 | #include "asm/bug.h" |
|---|
| 24 | 24 | #include "data-convert-bt.h" |
|---|
| 25 | 25 | #include "session.h" |
|---|
| 26 | | -#include "util.h" |
|---|
| 27 | 26 | #include "debug.h" |
|---|
| 28 | 27 | #include "tool.h" |
|---|
| 29 | 28 | #include "evlist.h" |
|---|
| 30 | 29 | #include "evsel.h" |
|---|
| 31 | 30 | #include "machine.h" |
|---|
| 32 | 31 | #include "config.h" |
|---|
| 33 | | -#include "sane_ctype.h" |
|---|
| 32 | +#include <linux/ctype.h> |
|---|
| 33 | +#include <linux/err.h> |
|---|
| 34 | +#include <linux/time64.h> |
|---|
| 35 | +#include "util.h" |
|---|
| 36 | +#include "clockid.h" |
|---|
| 34 | 37 | |
|---|
| 35 | 38 | #define pr_N(n, fmt, ...) \ |
|---|
| 36 | 39 | eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) |
|---|
| .. | .. |
|---|
| 182 | 185 | } |
|---|
| 183 | 186 | |
|---|
| 184 | 187 | static struct bt_ctf_field_type* |
|---|
| 185 | | -get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) |
|---|
| 188 | +get_tracepoint_field_type(struct ctf_writer *cw, struct tep_format_field *field) |
|---|
| 186 | 189 | { |
|---|
| 187 | 190 | unsigned long flags = field->flags; |
|---|
| 188 | 191 | |
|---|
| 189 | | - if (flags & FIELD_IS_STRING) |
|---|
| 192 | + if (flags & TEP_FIELD_IS_STRING) |
|---|
| 190 | 193 | return cw->data.string; |
|---|
| 191 | 194 | |
|---|
| 192 | | - if (!(flags & FIELD_IS_SIGNED)) { |
|---|
| 195 | + if (!(flags & TEP_FIELD_IS_SIGNED)) { |
|---|
| 193 | 196 | /* unsigned long are mostly pointers */ |
|---|
| 194 | | - if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) |
|---|
| 197 | + if (flags & TEP_FIELD_IS_LONG || flags & TEP_FIELD_IS_POINTER) |
|---|
| 195 | 198 | return cw->data.u64_hex; |
|---|
| 196 | 199 | } |
|---|
| 197 | 200 | |
|---|
| 198 | | - if (flags & FIELD_IS_SIGNED) { |
|---|
| 201 | + if (flags & TEP_FIELD_IS_SIGNED) { |
|---|
| 199 | 202 | if (field->size == 8) |
|---|
| 200 | 203 | return cw->data.s64; |
|---|
| 201 | 204 | else |
|---|
| .. | .. |
|---|
| 287 | 290 | struct bt_ctf_event_class *event_class, |
|---|
| 288 | 291 | struct bt_ctf_event *event, |
|---|
| 289 | 292 | struct perf_sample *sample, |
|---|
| 290 | | - struct format_field *fmtf) |
|---|
| 293 | + struct tep_format_field *fmtf) |
|---|
| 291 | 294 | { |
|---|
| 292 | 295 | struct bt_ctf_field_type *type; |
|---|
| 293 | 296 | struct bt_ctf_field *array_field; |
|---|
| .. | .. |
|---|
| 304 | 307 | name = fmtf->alias; |
|---|
| 305 | 308 | offset = fmtf->offset; |
|---|
| 306 | 309 | len = fmtf->size; |
|---|
| 307 | | - if (flags & FIELD_IS_STRING) |
|---|
| 308 | | - flags &= ~FIELD_IS_ARRAY; |
|---|
| 310 | + if (flags & TEP_FIELD_IS_STRING) |
|---|
| 311 | + flags &= ~TEP_FIELD_IS_ARRAY; |
|---|
| 309 | 312 | |
|---|
| 310 | | - if (flags & FIELD_IS_DYNAMIC) { |
|---|
| 313 | + if (flags & TEP_FIELD_IS_DYNAMIC) { |
|---|
| 311 | 314 | unsigned long long tmp_val; |
|---|
| 312 | 315 | |
|---|
| 313 | | - tmp_val = tep_read_number(fmtf->event->pevent, |
|---|
| 316 | + tmp_val = tep_read_number(fmtf->event->tep, |
|---|
| 314 | 317 | data + offset, len); |
|---|
| 315 | 318 | offset = tmp_val; |
|---|
| 316 | 319 | len = offset >> 16; |
|---|
| 317 | 320 | offset &= 0xffff; |
|---|
| 318 | 321 | } |
|---|
| 319 | 322 | |
|---|
| 320 | | - if (flags & FIELD_IS_ARRAY) { |
|---|
| 323 | + if (flags & TEP_FIELD_IS_ARRAY) { |
|---|
| 321 | 324 | |
|---|
| 322 | 325 | type = bt_ctf_event_class_get_field_by_name( |
|---|
| 323 | 326 | event_class, name); |
|---|
| .. | .. |
|---|
| 338 | 341 | type = get_tracepoint_field_type(cw, fmtf); |
|---|
| 339 | 342 | |
|---|
| 340 | 343 | for (i = 0; i < n_items; i++) { |
|---|
| 341 | | - if (flags & FIELD_IS_ARRAY) |
|---|
| 344 | + if (flags & TEP_FIELD_IS_ARRAY) |
|---|
| 342 | 345 | field = bt_ctf_field_array_get_field(array_field, i); |
|---|
| 343 | 346 | else |
|---|
| 344 | 347 | field = bt_ctf_field_create(type); |
|---|
| .. | .. |
|---|
| 348 | 351 | return -1; |
|---|
| 349 | 352 | } |
|---|
| 350 | 353 | |
|---|
| 351 | | - if (flags & FIELD_IS_STRING) |
|---|
| 354 | + if (flags & TEP_FIELD_IS_STRING) |
|---|
| 352 | 355 | ret = string_set_value(field, data + offset + i * len); |
|---|
| 353 | 356 | else { |
|---|
| 354 | 357 | unsigned long long value_int; |
|---|
| 355 | 358 | |
|---|
| 356 | 359 | value_int = tep_read_number( |
|---|
| 357 | | - fmtf->event->pevent, |
|---|
| 360 | + fmtf->event->tep, |
|---|
| 358 | 361 | data + offset + i * len, len); |
|---|
| 359 | 362 | |
|---|
| 360 | | - if (!(flags & FIELD_IS_SIGNED)) |
|---|
| 363 | + if (!(flags & TEP_FIELD_IS_SIGNED)) |
|---|
| 361 | 364 | ret = bt_ctf_field_unsigned_integer_set_value( |
|---|
| 362 | 365 | field, value_int); |
|---|
| 363 | 366 | else |
|---|
| .. | .. |
|---|
| 369 | 372 | pr_err("failed to set file value %s\n", name); |
|---|
| 370 | 373 | goto err_put_field; |
|---|
| 371 | 374 | } |
|---|
| 372 | | - if (!(flags & FIELD_IS_ARRAY)) { |
|---|
| 375 | + if (!(flags & TEP_FIELD_IS_ARRAY)) { |
|---|
| 373 | 376 | ret = bt_ctf_event_set_payload(event, name, field); |
|---|
| 374 | 377 | if (ret) { |
|---|
| 375 | 378 | pr_err("failed to set payload %s\n", name); |
|---|
| .. | .. |
|---|
| 378 | 381 | } |
|---|
| 379 | 382 | bt_ctf_field_put(field); |
|---|
| 380 | 383 | } |
|---|
| 381 | | - if (flags & FIELD_IS_ARRAY) { |
|---|
| 384 | + if (flags & TEP_FIELD_IS_ARRAY) { |
|---|
| 382 | 385 | ret = bt_ctf_event_set_payload(event, name, array_field); |
|---|
| 383 | 386 | if (ret) { |
|---|
| 384 | 387 | pr_err("Failed add payload array %s\n", name); |
|---|
| .. | .. |
|---|
| 396 | 399 | static int add_tracepoint_fields_values(struct ctf_writer *cw, |
|---|
| 397 | 400 | struct bt_ctf_event_class *event_class, |
|---|
| 398 | 401 | struct bt_ctf_event *event, |
|---|
| 399 | | - struct format_field *fields, |
|---|
| 402 | + struct tep_format_field *fields, |
|---|
| 400 | 403 | struct perf_sample *sample) |
|---|
| 401 | 404 | { |
|---|
| 402 | | - struct format_field *field; |
|---|
| 405 | + struct tep_format_field *field; |
|---|
| 403 | 406 | int ret; |
|---|
| 404 | 407 | |
|---|
| 405 | 408 | for (field = fields; field; field = field->next) { |
|---|
| .. | .. |
|---|
| 414 | 417 | static int add_tracepoint_values(struct ctf_writer *cw, |
|---|
| 415 | 418 | struct bt_ctf_event_class *event_class, |
|---|
| 416 | 419 | struct bt_ctf_event *event, |
|---|
| 417 | | - struct perf_evsel *evsel, |
|---|
| 420 | + struct evsel *evsel, |
|---|
| 418 | 421 | struct perf_sample *sample) |
|---|
| 419 | 422 | { |
|---|
| 420 | | - struct format_field *common_fields = evsel->tp_format->format.common_fields; |
|---|
| 421 | | - struct format_field *fields = evsel->tp_format->format.fields; |
|---|
| 423 | + struct tep_format_field *common_fields = evsel->tp_format->format.common_fields; |
|---|
| 424 | + struct tep_format_field *fields = evsel->tp_format->format.fields; |
|---|
| 422 | 425 | int ret; |
|---|
| 423 | 426 | |
|---|
| 424 | 427 | ret = add_tracepoint_fields_values(cw, event_class, event, |
|---|
| .. | .. |
|---|
| 585 | 588 | |
|---|
| 586 | 589 | static int add_generic_values(struct ctf_writer *cw, |
|---|
| 587 | 590 | struct bt_ctf_event *event, |
|---|
| 588 | | - struct perf_evsel *evsel, |
|---|
| 591 | + struct evsel *evsel, |
|---|
| 589 | 592 | struct perf_sample *sample) |
|---|
| 590 | 593 | { |
|---|
| 591 | | - u64 type = evsel->attr.sample_type; |
|---|
| 594 | + u64 type = evsel->core.attr.sample_type; |
|---|
| 592 | 595 | int ret; |
|---|
| 593 | 596 | |
|---|
| 594 | 597 | /* |
|---|
| .. | .. |
|---|
| 754 | 757 | } |
|---|
| 755 | 758 | |
|---|
| 756 | 759 | static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample, |
|---|
| 757 | | - struct perf_evsel *evsel) |
|---|
| 760 | + struct evsel *evsel) |
|---|
| 758 | 761 | { |
|---|
| 759 | 762 | int cpu = 0; |
|---|
| 760 | 763 | |
|---|
| 761 | | - if (evsel->attr.sample_type & PERF_SAMPLE_CPU) |
|---|
| 764 | + if (evsel->core.attr.sample_type & PERF_SAMPLE_CPU) |
|---|
| 762 | 765 | cpu = sample->cpu; |
|---|
| 763 | 766 | |
|---|
| 764 | 767 | if (cpu > cw->stream_cnt) { |
|---|
| .. | .. |
|---|
| 786 | 789 | static int process_sample_event(struct perf_tool *tool, |
|---|
| 787 | 790 | union perf_event *_event, |
|---|
| 788 | 791 | struct perf_sample *sample, |
|---|
| 789 | | - struct perf_evsel *evsel, |
|---|
| 792 | + struct evsel *evsel, |
|---|
| 790 | 793 | struct machine *machine __maybe_unused) |
|---|
| 791 | 794 | { |
|---|
| 792 | 795 | struct convert *c = container_of(tool, struct convert, tool); |
|---|
| .. | .. |
|---|
| 796 | 799 | struct bt_ctf_event_class *event_class; |
|---|
| 797 | 800 | struct bt_ctf_event *event; |
|---|
| 798 | 801 | int ret; |
|---|
| 799 | | - unsigned long type = evsel->attr.sample_type; |
|---|
| 802 | + unsigned long type = evsel->core.attr.sample_type; |
|---|
| 800 | 803 | |
|---|
| 801 | 804 | if (WARN_ONCE(!priv, "Failed to setup all events.\n")) |
|---|
| 802 | 805 | return 0; |
|---|
| .. | .. |
|---|
| 821 | 824 | if (ret) |
|---|
| 822 | 825 | return -1; |
|---|
| 823 | 826 | |
|---|
| 824 | | - if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { |
|---|
| 827 | + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { |
|---|
| 825 | 828 | ret = add_tracepoint_values(cw, event_class, event, |
|---|
| 826 | 829 | evsel, sample); |
|---|
| 827 | 830 | if (ret) |
|---|
| .. | .. |
|---|
| 835 | 838 | return -1; |
|---|
| 836 | 839 | } |
|---|
| 837 | 840 | |
|---|
| 838 | | - if (perf_evsel__is_bpf_output(evsel)) { |
|---|
| 841 | + if (evsel__is_bpf_output(evsel)) { |
|---|
| 839 | 842 | ret = add_bpf_output_values(event_class, event, sample); |
|---|
| 840 | 843 | if (ret) |
|---|
| 841 | 844 | return -1; |
|---|
| .. | .. |
|---|
| 970 | 973 | |
|---|
| 971 | 974 | static int event_class_add_field(struct bt_ctf_event_class *event_class, |
|---|
| 972 | 975 | struct bt_ctf_field_type *type, |
|---|
| 973 | | - struct format_field *field) |
|---|
| 976 | + struct tep_format_field *field) |
|---|
| 974 | 977 | { |
|---|
| 975 | 978 | struct bt_ctf_field_type *t = NULL; |
|---|
| 976 | 979 | char *name; |
|---|
| .. | .. |
|---|
| 1009 | 1012 | } |
|---|
| 1010 | 1013 | |
|---|
| 1011 | 1014 | static int add_tracepoint_fields_types(struct ctf_writer *cw, |
|---|
| 1012 | | - struct format_field *fields, |
|---|
| 1015 | + struct tep_format_field *fields, |
|---|
| 1013 | 1016 | struct bt_ctf_event_class *event_class) |
|---|
| 1014 | 1017 | { |
|---|
| 1015 | | - struct format_field *field; |
|---|
| 1018 | + struct tep_format_field *field; |
|---|
| 1016 | 1019 | int ret; |
|---|
| 1017 | 1020 | |
|---|
| 1018 | 1021 | for (field = fields; field; field = field->next) { |
|---|
| .. | .. |
|---|
| 1030 | 1033 | * type and don't care that it is an array. What we don't |
|---|
| 1031 | 1034 | * support is an array of strings. |
|---|
| 1032 | 1035 | */ |
|---|
| 1033 | | - if (flags & FIELD_IS_STRING) |
|---|
| 1034 | | - flags &= ~FIELD_IS_ARRAY; |
|---|
| 1036 | + if (flags & TEP_FIELD_IS_STRING) |
|---|
| 1037 | + flags &= ~TEP_FIELD_IS_ARRAY; |
|---|
| 1035 | 1038 | |
|---|
| 1036 | | - if (flags & FIELD_IS_ARRAY) |
|---|
| 1039 | + if (flags & TEP_FIELD_IS_ARRAY) |
|---|
| 1037 | 1040 | type = bt_ctf_field_type_array_create(type, field->arraylen); |
|---|
| 1038 | 1041 | |
|---|
| 1039 | 1042 | ret = event_class_add_field(event_class, type, field); |
|---|
| 1040 | 1043 | |
|---|
| 1041 | | - if (flags & FIELD_IS_ARRAY) |
|---|
| 1044 | + if (flags & TEP_FIELD_IS_ARRAY) |
|---|
| 1042 | 1045 | bt_ctf_field_type_put(type); |
|---|
| 1043 | 1046 | |
|---|
| 1044 | 1047 | if (ret) { |
|---|
| .. | .. |
|---|
| 1052 | 1055 | } |
|---|
| 1053 | 1056 | |
|---|
| 1054 | 1057 | static int add_tracepoint_types(struct ctf_writer *cw, |
|---|
| 1055 | | - struct perf_evsel *evsel, |
|---|
| 1058 | + struct evsel *evsel, |
|---|
| 1056 | 1059 | struct bt_ctf_event_class *class) |
|---|
| 1057 | 1060 | { |
|---|
| 1058 | | - struct format_field *common_fields = evsel->tp_format->format.common_fields; |
|---|
| 1059 | | - struct format_field *fields = evsel->tp_format->format.fields; |
|---|
| 1061 | + struct tep_format_field *common_fields = evsel->tp_format->format.common_fields; |
|---|
| 1062 | + struct tep_format_field *fields = evsel->tp_format->format.fields; |
|---|
| 1060 | 1063 | int ret; |
|---|
| 1061 | 1064 | |
|---|
| 1062 | 1065 | ret = add_tracepoint_fields_types(cw, common_fields, class); |
|---|
| .. | .. |
|---|
| 1085 | 1088 | return bt_ctf_event_class_add_field(class, seq_type, "raw_data"); |
|---|
| 1086 | 1089 | } |
|---|
| 1087 | 1090 | |
|---|
| 1088 | | -static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, |
|---|
| 1091 | +static int add_generic_types(struct ctf_writer *cw, struct evsel *evsel, |
|---|
| 1089 | 1092 | struct bt_ctf_event_class *event_class) |
|---|
| 1090 | 1093 | { |
|---|
| 1091 | | - u64 type = evsel->attr.sample_type; |
|---|
| 1094 | + u64 type = evsel->core.attr.sample_type; |
|---|
| 1092 | 1095 | |
|---|
| 1093 | 1096 | /* |
|---|
| 1094 | 1097 | * missing: |
|---|
| .. | .. |
|---|
| 1151 | 1154 | return 0; |
|---|
| 1152 | 1155 | } |
|---|
| 1153 | 1156 | |
|---|
| 1154 | | -static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel) |
|---|
| 1157 | +static int add_event(struct ctf_writer *cw, struct evsel *evsel) |
|---|
| 1155 | 1158 | { |
|---|
| 1156 | 1159 | struct bt_ctf_event_class *event_class; |
|---|
| 1157 | 1160 | struct evsel_priv *priv; |
|---|
| 1158 | | - const char *name = perf_evsel__name(evsel); |
|---|
| 1161 | + const char *name = evsel__name(evsel); |
|---|
| 1159 | 1162 | int ret; |
|---|
| 1160 | 1163 | |
|---|
| 1161 | | - pr("Adding event '%s' (type %d)\n", name, evsel->attr.type); |
|---|
| 1164 | + pr("Adding event '%s' (type %d)\n", name, evsel->core.attr.type); |
|---|
| 1162 | 1165 | |
|---|
| 1163 | 1166 | event_class = bt_ctf_event_class_create(name); |
|---|
| 1164 | 1167 | if (!event_class) |
|---|
| .. | .. |
|---|
| 1168 | 1171 | if (ret) |
|---|
| 1169 | 1172 | goto err; |
|---|
| 1170 | 1173 | |
|---|
| 1171 | | - if (evsel->attr.type == PERF_TYPE_TRACEPOINT) { |
|---|
| 1174 | + if (evsel->core.attr.type == PERF_TYPE_TRACEPOINT) { |
|---|
| 1172 | 1175 | ret = add_tracepoint_types(cw, evsel, event_class); |
|---|
| 1173 | 1176 | if (ret) |
|---|
| 1174 | 1177 | goto err; |
|---|
| 1175 | 1178 | } |
|---|
| 1176 | 1179 | |
|---|
| 1177 | | - if (perf_evsel__is_bpf_output(evsel)) { |
|---|
| 1180 | + if (evsel__is_bpf_output(evsel)) { |
|---|
| 1178 | 1181 | ret = add_bpf_output_types(cw, event_class); |
|---|
| 1179 | 1182 | if (ret) |
|---|
| 1180 | 1183 | goto err; |
|---|
| .. | .. |
|---|
| 1202 | 1205 | |
|---|
| 1203 | 1206 | static int setup_events(struct ctf_writer *cw, struct perf_session *session) |
|---|
| 1204 | 1207 | { |
|---|
| 1205 | | - struct perf_evlist *evlist = session->evlist; |
|---|
| 1206 | | - struct perf_evsel *evsel; |
|---|
| 1208 | + struct evlist *evlist = session->evlist; |
|---|
| 1209 | + struct evsel *evsel; |
|---|
| 1207 | 1210 | int ret; |
|---|
| 1208 | 1211 | |
|---|
| 1209 | 1212 | evlist__for_each_entry(evlist, evsel) { |
|---|
| .. | .. |
|---|
| 1309 | 1312 | |
|---|
| 1310 | 1313 | static void cleanup_events(struct perf_session *session) |
|---|
| 1311 | 1314 | { |
|---|
| 1312 | | - struct perf_evlist *evlist = session->evlist; |
|---|
| 1313 | | - struct perf_evsel *evsel; |
|---|
| 1315 | + struct evlist *evlist = session->evlist; |
|---|
| 1316 | + struct evsel *evsel; |
|---|
| 1314 | 1317 | |
|---|
| 1315 | 1318 | evlist__for_each_entry(evlist, evsel) { |
|---|
| 1316 | 1319 | struct evsel_priv *priv; |
|---|
| .. | .. |
|---|
| 1320 | 1323 | zfree(&evsel->priv); |
|---|
| 1321 | 1324 | } |
|---|
| 1322 | 1325 | |
|---|
| 1323 | | - perf_evlist__delete(evlist); |
|---|
| 1326 | + evlist__delete(evlist); |
|---|
| 1324 | 1327 | session->evlist = NULL; |
|---|
| 1325 | 1328 | } |
|---|
| 1326 | 1329 | |
|---|
| .. | .. |
|---|
| 1354 | 1357 | for (cpu = 0; cpu < cw->stream_cnt; cpu++) |
|---|
| 1355 | 1358 | ctf_stream__delete(cw->stream[cpu]); |
|---|
| 1356 | 1359 | |
|---|
| 1357 | | - free(cw->stream); |
|---|
| 1360 | + zfree(&cw->stream); |
|---|
| 1358 | 1361 | } |
|---|
| 1359 | 1362 | |
|---|
| 1360 | 1363 | static int ctf_writer__setup_env(struct ctf_writer *cw, |
|---|
| .. | .. |
|---|
| 1381 | 1384 | return 0; |
|---|
| 1382 | 1385 | } |
|---|
| 1383 | 1386 | |
|---|
| 1384 | | -static int ctf_writer__setup_clock(struct ctf_writer *cw) |
|---|
| 1387 | +static int ctf_writer__setup_clock(struct ctf_writer *cw, |
|---|
| 1388 | + struct perf_session *session, |
|---|
| 1389 | + bool tod) |
|---|
| 1385 | 1390 | { |
|---|
| 1386 | 1391 | struct bt_ctf_clock *clock = cw->clock; |
|---|
| 1392 | + const char *desc = "perf clock"; |
|---|
| 1393 | + int64_t offset = 0; |
|---|
| 1387 | 1394 | |
|---|
| 1388 | | - bt_ctf_clock_set_description(clock, "perf clock"); |
|---|
| 1395 | + if (tod) { |
|---|
| 1396 | + struct perf_env *env = &session->header.env; |
|---|
| 1397 | + |
|---|
| 1398 | + if (!env->clock.enabled) { |
|---|
| 1399 | + pr_err("Can't provide --tod time, missing clock data. " |
|---|
| 1400 | + "Please record with -k/--clockid option.\n"); |
|---|
| 1401 | + return -1; |
|---|
| 1402 | + } |
|---|
| 1403 | + |
|---|
| 1404 | + desc = clockid_name(env->clock.clockid); |
|---|
| 1405 | + offset = env->clock.tod_ns - env->clock.clockid_ns; |
|---|
| 1406 | + } |
|---|
| 1389 | 1407 | |
|---|
| 1390 | 1408 | #define SET(__n, __v) \ |
|---|
| 1391 | 1409 | do { \ |
|---|
| .. | .. |
|---|
| 1394 | 1412 | } while (0) |
|---|
| 1395 | 1413 | |
|---|
| 1396 | 1414 | SET(frequency, 1000000000); |
|---|
| 1397 | | - SET(offset_s, 0); |
|---|
| 1398 | | - SET(offset, 0); |
|---|
| 1415 | + SET(offset, offset); |
|---|
| 1416 | + SET(description, desc); |
|---|
| 1399 | 1417 | SET(precision, 10); |
|---|
| 1400 | 1418 | SET(is_absolute, 0); |
|---|
| 1401 | 1419 | |
|---|
| .. | .. |
|---|
| 1481 | 1499 | memset(cw, 0, sizeof(*cw)); |
|---|
| 1482 | 1500 | } |
|---|
| 1483 | 1501 | |
|---|
| 1484 | | -static int ctf_writer__init(struct ctf_writer *cw, const char *path) |
|---|
| 1502 | +static int ctf_writer__init(struct ctf_writer *cw, const char *path, |
|---|
| 1503 | + struct perf_session *session, bool tod) |
|---|
| 1485 | 1504 | { |
|---|
| 1486 | 1505 | struct bt_ctf_writer *writer; |
|---|
| 1487 | 1506 | struct bt_ctf_stream_class *stream_class; |
|---|
| .. | .. |
|---|
| 1505 | 1524 | |
|---|
| 1506 | 1525 | cw->clock = clock; |
|---|
| 1507 | 1526 | |
|---|
| 1508 | | - if (ctf_writer__setup_clock(cw)) { |
|---|
| 1527 | + if (ctf_writer__setup_clock(cw, session, tod)) { |
|---|
| 1509 | 1528 | pr("Failed to setup CTF clock.\n"); |
|---|
| 1510 | 1529 | goto err_cleanup; |
|---|
| 1511 | 1530 | } |
|---|
| .. | .. |
|---|
| 1578 | 1597 | { |
|---|
| 1579 | 1598 | struct perf_session *session; |
|---|
| 1580 | 1599 | struct perf_data data = { |
|---|
| 1581 | | - .file.path = input, |
|---|
| 1600 | + .path = input, |
|---|
| 1582 | 1601 | .mode = PERF_DATA_MODE_READ, |
|---|
| 1583 | 1602 | .force = opts->force, |
|---|
| 1584 | 1603 | }; |
|---|
| .. | .. |
|---|
| 1613 | 1632 | if (err) |
|---|
| 1614 | 1633 | return err; |
|---|
| 1615 | 1634 | |
|---|
| 1616 | | - /* CTF writer */ |
|---|
| 1617 | | - if (ctf_writer__init(cw, path)) |
|---|
| 1618 | | - return -1; |
|---|
| 1619 | | - |
|---|
| 1620 | 1635 | err = -1; |
|---|
| 1621 | 1636 | /* perf.data session */ |
|---|
| 1622 | 1637 | session = perf_session__new(&data, 0, &c.tool); |
|---|
| 1623 | | - if (!session) |
|---|
| 1624 | | - goto free_writer; |
|---|
| 1638 | + if (IS_ERR(session)) |
|---|
| 1639 | + return PTR_ERR(session); |
|---|
| 1640 | + |
|---|
| 1641 | + /* CTF writer */ |
|---|
| 1642 | + if (ctf_writer__init(cw, path, session, opts->tod)) |
|---|
| 1643 | + goto free_session; |
|---|
| 1625 | 1644 | |
|---|
| 1626 | 1645 | if (c.queue_size) { |
|---|
| 1627 | 1646 | ordered_events__set_alloc_size(&session->ordered_events, |
|---|
| .. | .. |
|---|
| 1630 | 1649 | |
|---|
| 1631 | 1650 | /* CTF writer env/clock setup */ |
|---|
| 1632 | 1651 | if (ctf_writer__setup_env(cw, session)) |
|---|
| 1633 | | - goto free_session; |
|---|
| 1652 | + goto free_writer; |
|---|
| 1634 | 1653 | |
|---|
| 1635 | 1654 | /* CTF events setup */ |
|---|
| 1636 | 1655 | if (setup_events(cw, session)) |
|---|
| 1637 | | - goto free_session; |
|---|
| 1656 | + goto free_writer; |
|---|
| 1638 | 1657 | |
|---|
| 1639 | 1658 | if (opts->all && setup_non_sample_events(cw, session)) |
|---|
| 1640 | | - goto free_session; |
|---|
| 1659 | + goto free_writer; |
|---|
| 1641 | 1660 | |
|---|
| 1642 | 1661 | if (setup_streams(cw, session)) |
|---|
| 1643 | | - goto free_session; |
|---|
| 1662 | + goto free_writer; |
|---|
| 1644 | 1663 | |
|---|
| 1645 | 1664 | err = perf_session__process_events(session); |
|---|
| 1646 | 1665 | if (!err) |
|---|
| .. | .. |
|---|
| 1650 | 1669 | |
|---|
| 1651 | 1670 | fprintf(stderr, |
|---|
| 1652 | 1671 | "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", |
|---|
| 1653 | | - data.file.path, path); |
|---|
| 1672 | + data.path, path); |
|---|
| 1654 | 1673 | |
|---|
| 1655 | 1674 | fprintf(stderr, |
|---|
| 1656 | 1675 | "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples", |
|---|
| .. | .. |
|---|
| 1668 | 1687 | |
|---|
| 1669 | 1688 | return err; |
|---|
| 1670 | 1689 | |
|---|
| 1671 | | -free_session: |
|---|
| 1672 | | - perf_session__delete(session); |
|---|
| 1673 | 1690 | free_writer: |
|---|
| 1674 | 1691 | ctf_writer__cleanup(cw); |
|---|
| 1692 | +free_session: |
|---|
| 1693 | + perf_session__delete(session); |
|---|
| 1675 | 1694 | pr_err("Error during conversion setup.\n"); |
|---|
| 1676 | 1695 | return err; |
|---|
| 1677 | 1696 | } |
|---|