/*
* CTF writing support via babeltrace.
*
* Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
* Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*
* Released under the GPL v2. (and only v2, not any later version)
*/
#include <linux/compiler.h>
#include <babeltrace/ctf-writer/writer.h>
#include <babeltrace/ctf-writer/clock.h>
#include <babeltrace/ctf-writer/stream.h>
#include <babeltrace/ctf-writer/event.h>
#include <babeltrace/ctf-writer/event-types.h>
#include <babeltrace/ctf-writer/event-fields.h>
#include <babeltrace/ctf-ir/utils.h>
#include <babeltrace/ctf/events.h>
#include <traceevent/event-parse.h>
#include "asm/bug.h"
#include "data-convert-bt.h"
#include "session.h"
#include "util.h"
#include "debug.h"
#include "tool.h"
#include "evlist.h"
#include "evsel.h"
#include "machine.h"
#define pr_N(n, fmt, ...) \
eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
#define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
#define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
#define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
struct evsel_priv {
struct bt_ctf_event_class *event_class;
};
#define MAX_CPUS 4096
struct ctf_stream {
struct bt_ctf_stream *stream;
int cpu;
u32 count;
};
struct ctf_writer {
/* writer primitives */
struct bt_ctf_writer *writer;
struct ctf_stream **stream;
int stream_cnt;
struct bt_ctf_stream_class *stream_class;
struct bt_ctf_clock *clock;
/* data types */
union {
struct {
struct bt_ctf_field_type *s64;
struct bt_ctf_field_type *u64;
struct bt_ctf_field_type *s32;
struct bt_ctf_field_type *u32;
struct bt_ctf_field_type *string;
struct bt_ctf_field_type *u64_hex;
};
struct bt_ctf_field_type *array[6];
} data;
};
struct convert {
struct perf_tool tool;
struct ctf_writer writer;
u64 events_size;
u64 events_count;
/* Ordered events configured queue size. */
u64 queue_size;
};
static int value_set(struct bt_ctf_field_type *type,
struct bt_ctf_event *event,
const char *name, u64 val)
{
struct bt_ctf_field *field;
bool sign = bt_ctf_field_type_integer_get_signed(type);
int ret;
field = bt_ctf_field_create(type);
if (!field) {
pr_err("failed to create a field %s\n", name);
return -1;
}
if (sign) {
ret = bt_ctf_field_signed_integer_set_value(field, val);
if (ret) {
pr_err("failed to set field value %s\n", name);
goto err;
}
} else {
ret = bt_ctf_field_unsigned_integer_set_value(field, val);
if (ret) {
pr_err("failed to set field value %s\n", name);
goto err;
}
}
ret = bt_ctf_event_set_payload(event, name, field);
if (ret) {
pr_err("failed to set payload %s\n", name);
goto err;
}
pr2(" SET [%s = %" PRIu64 "]\n", name, val);
err:
bt_ctf_field_put(field);
return ret;
}
#define __FUNC_VALUE_SET(_name, _val_type) \
static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \
struct bt_ctf_event *event, \
const char *name, \
_val_type val) \
{ \
struct bt_ctf_field_type *type = cw->data._name; \
return value_set(type, event, name, (u64) val); \
}
#define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
FUNC_VALUE_SET(s32)
FUNC_VALUE_SET(u32)
FUNC_VALUE_SET(s64)
FUNC_VALUE_SET(u64)
__FUNC_VALUE_SET(u64_hex, u64)
static struct bt_ctf_field_type*
get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
{
unsigned long flags = field->flags;
if (flags & FIELD_IS_STRING)
return cw->data.string;
if (!(flags & FIELD_IS_SIGNED)) {
/* unsigned long are mostly pointers */
if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
return cw->data.u64_hex;
}
if (flags & FIELD_IS_SIGNED) {
if (field->size == 8)
return cw->data.s64;
else
return cw->data.s32;
}
if (field->size == 8)
return cw