numam-dpdk/lib/eal/common/eal_common_trace_ctf.c
Bruce Richardson 99a2dd955f lib: remove librte_ prefix from directory names
There is no reason for the DPDK libraries to all have 'librte_' prefix on
the directory names. This prefix makes the directory names longer and also
makes it awkward to add features referring to individual libraries in the
build - should the lib names be specified with or without the prefix.
Therefore, we can just remove the library prefix and use the library's
unique name as the directory name, i.e. 'eal' rather than 'librte_eal'

Signed-off-by: Bruce Richardson <bruce.richardson@intel.com>
2021-04-21 14:04:09 +02:00

417 lines
8.4 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright(C) 2020 Marvell International Ltd.
*/
#include <inttypes.h>
#include <time.h>
#include <rte_byteorder.h>
#include <rte_common.h>
#include <rte_time.h>
#include <rte_trace.h>
#include <rte_version.h>
#include "eal_trace.h"
__rte_format_printf(2, 0)
static int
metadata_printf(char **str, const char *fmt, ...)
{
va_list ap;
int rc;
*str = NULL;
va_start(ap, fmt);
rc = vasprintf(str, fmt, ap);
va_end(ap);
return rc;
}
static int
meta_copy(char **meta, int *offset, char *str, int rc)
{
int count = *offset;
char *ptr = *meta;
if (rc < 0)
return rc;
ptr = realloc(ptr, count + rc + 1);
if (ptr == NULL)
goto free_str;
memcpy(RTE_PTR_ADD(ptr, count), str, rc);
ptr[count + rc] = '\0';
count += rc;
free(str);
*meta = ptr;
*offset = count;
return rc;
free_str:
if (str)
free(str);
return -ENOMEM;
}
static int
meta_data_type_emit(char **meta, int *offset)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"/* CTF 1.8 */\n"
"typealias integer {size = 8; base = x;}:= uint8_t;\n"
"typealias integer {size = 16; base = x;} := uint16_t;\n"
"typealias integer {size = 32; base = x;} := uint32_t;\n"
"typealias integer {size = 64; base = x;} := uint64_t;\n"
"typealias integer {size = 8; signed = true;} := int8_t;\n"
"typealias integer {size = 16; signed = true;} := int16_t;\n"
"typealias integer {size = 32; signed = true;} := int32_t;\n"
"typealias integer {size = 64; signed = true;} := int64_t;\n"
#ifdef RTE_ARCH_64
"typealias integer {size = 64; base = x;} := uintptr_t;\n"
#else
"typealias integer {size = 32; base = x;} := uintptr_t;\n"
#endif
#ifdef RTE_ARCH_64
"typealias integer {size = 64; base = x;} := long;\n"
#else
"typealias integer {size = 32; base = x;} := long;\n"
#endif
"typealias integer {size = 8; signed = false; encoding = ASCII; } := string_bounded_t;\n\n"
#ifdef RTE_ARCH_64
"typealias integer {size = 64; base = x;} := size_t;\n"
#else
"typealias integer {size = 32; base = x;} := size_t;\n"
#endif
"typealias floating_point {\n"
" exp_dig = 8;\n"
" mant_dig = 24;\n"
"} := float;\n\n"
"typealias floating_point {\n"
" exp_dig = 11;\n"
" mant_dig = 53;\n"
"} := double;\n\n");
return meta_copy(meta, offset, str, rc);
}
static int
is_be(void)
{
#if RTE_BYTE_ORDER == RTE_BIG_ENDIAN
return 1;
#else
return 0;
#endif
}
static int
meta_header_emit(char **meta, int *offset)
{
struct trace *trace = trace_obj_get();
char uustr[RTE_UUID_STRLEN];
char *str = NULL;
int rc;
rte_uuid_unparse(trace->uuid, uustr, RTE_UUID_STRLEN);
rc = metadata_printf(&str,
"trace {\n"
" major = 1;\n"
" minor = 8;\n"
" uuid = \"%s\";\n"
" byte_order = %s;\n"
" packet.header := struct {\n"
" uint32_t magic;\n"
" uint8_t uuid[16];\n"
" };\n"
"};\n\n", uustr, is_be() ? "be" : "le");
return meta_copy(meta, offset, str, rc);
}
static int
meta_env_emit(char **meta, int *offset)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"env {\n"
" dpdk_version = \"%s\";\n"
" tracer_name = \"dpdk\";\n"
"};\n\n", rte_version());
return meta_copy(meta, offset, str, rc);
}
static int
meta_clock_pass1_emit(char **meta, int *offset)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"clock {\n"
" name = \"dpdk\";\n"
" freq = ");
return meta_copy(meta, offset, str, rc);
}
static int
meta_clock_pass2_emit(char **meta, int *offset)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"%20"PRIu64";\n"
" offset_s =", 0);
return meta_copy(meta, offset, str, rc);
}
static int
meta_clock_pass3_emit(char **meta, int *offset)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"%20"PRIu64";\n"
" offset =", 0);
return meta_copy(meta, offset, str, rc);
}
static int
meta_clock_pass4_emit(char **meta, int *offset)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"%20"PRIu64";\n};\n\n"
"typealias integer {\n"
" size = 48; align = 1; signed = false;\n"
" map = clock.dpdk.value;\n"
"} := uint48_clock_dpdk_t;\n\n", 0);
return meta_copy(meta, offset, str, rc);
}
static int
meta_stream_emit(char **meta, int *offset)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"stream {\n"
" packet.context := struct {\n"
" uint32_t cpu_id;\n"
" string_bounded_t name[32];\n"
" };\n"
" event.header := struct {\n"
" uint48_clock_dpdk_t timestamp;\n"
" uint16_t id;\n"
" } align(64);\n"
"};\n\n");
return meta_copy(meta, offset, str, rc);
}
static int
meta_event_emit(char **meta, int *offset, struct trace_point *tp)
{
char *str = NULL;
int rc;
rc = metadata_printf(&str,
"event {\n"
" id = %d;\n"
" name = \"%s\";\n"
" fields := struct {\n"
"%s"
" };\n"
"};\n\n", trace_id_get(tp->handle), tp->name,
tp->ctf_field != NULL ? tp->ctf_field : "");
return meta_copy(meta, offset, str, rc);
}
int
trace_metadata_create(void)
{
struct trace_point_head *tp_list = trace_list_head_get();
struct trace *trace = trace_obj_get();
struct trace_point *tp;
int rc, offset = 0;
char *meta = NULL;
rc = meta_data_type_emit(&meta, &offset);
if (rc < 0)
goto fail;
rc = meta_header_emit(&meta, &offset);
if (rc < 0)
goto fail;
rc = meta_env_emit(&meta, &offset);
if (rc < 0)
goto fail;
rc = meta_clock_pass1_emit(&meta, &offset);
if (rc < 0)
goto fail;
trace->ctf_meta_offset_freq = offset;
rc = meta_clock_pass2_emit(&meta, &offset);
if (rc < 0)
goto fail;
trace->ctf_meta_offset_freq_off_s = offset;
rc = meta_clock_pass3_emit(&meta, &offset);
if (rc < 0)
goto fail;
trace->ctf_meta_offset_freq_off = offset;
rc = meta_clock_pass4_emit(&meta, &offset);
if (rc < 0)
goto fail;
rc = meta_stream_emit(&meta, &offset);
if (rc < 0)
goto fail;
STAILQ_FOREACH(tp, tp_list, next)
if (meta_event_emit(&meta, &offset, tp) < 0)
goto fail;
trace->ctf_meta = meta;
return 0;
fail:
if (meta)
free(meta);
return -EBADF;
}
void
trace_metadata_destroy(void)
{
struct trace *trace = trace_obj_get();
if (trace->ctf_meta) {
free(trace->ctf_meta);
trace->ctf_meta = NULL;
}
}
static void
meta_fix_freq(struct trace *trace, char *meta)
{
char *str;
int rc;
str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq);
rc = sprintf(str, "%20"PRIu64"", rte_get_timer_hz());
str[rc] = ';';
}
static void
meta_fix_freq_offset(struct trace *trace, char *meta)
{
uint64_t uptime_tickes_floor, uptime_ticks, freq, uptime_sec;
uint64_t offset, offset_s;
char *str;
int rc;
uptime_ticks = trace->uptime_ticks &
((1ULL << __RTE_TRACE_EVENT_HEADER_ID_SHIFT) - 1);
freq = rte_get_tsc_hz();
uptime_tickes_floor = RTE_ALIGN_MUL_FLOOR(uptime_ticks, freq);
uptime_sec = uptime_tickes_floor / freq;
offset_s = trace->epoch_sec - uptime_sec;
offset = uptime_ticks - uptime_tickes_floor;
offset += trace->epoch_nsec * (freq / NSEC_PER_SEC);
str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off_s);
rc = sprintf(str, "%20"PRIu64"", offset_s);
str[rc] = ';';
str = RTE_PTR_ADD(meta, trace->ctf_meta_offset_freq_off);
rc = sprintf(str, "%20"PRIu64"", offset);
str[rc] = ';';
}
static void
meta_fixup(struct trace *trace, char *meta)
{
meta_fix_freq(trace, meta);
meta_fix_freq_offset(trace, meta);
}
int
rte_trace_metadata_dump(FILE *f)
{
struct trace *trace = trace_obj_get();
char *ctf_meta = trace->ctf_meta;
int rc;
if (!rte_trace_is_enabled())
return 0;
if (ctf_meta == NULL)
return -EINVAL;
if (!__atomic_load_n(&trace->ctf_fixup_done, __ATOMIC_SEQ_CST) &&
rte_get_timer_hz()) {
meta_fixup(trace, ctf_meta);
__atomic_store_n(&trace->ctf_fixup_done, 1, __ATOMIC_SEQ_CST);
}
rc = fprintf(f, "%s", ctf_meta);
return rc < 0 ? rc : 0;
}
char *trace_metadata_fixup_field(const char *field)
{
const char *ctf_reserved_words[] = {
"align",
"event",
};
unsigned int i;
char *out;
char *p;
/* reserved keywords */
for (i = 0; i < RTE_DIM(ctf_reserved_words); i++) {
if (strcmp(field, ctf_reserved_words[i]) != 0)
continue;
if (asprintf(&out, "_%s", ctf_reserved_words[i]) == -1)
out = NULL;
return out;
}
/* nothing to replace, return early */
if (strstr(field, ".") == NULL && strstr(field, "->") == NULL)
return NULL;
out = strdup(field);
if (out == NULL)
return NULL;
p = out;
while ((p = strstr(p, ".")) != NULL) {
p[0] = '_';
p++;
}
p = out;
while ((p = strstr(p, "->")) != NULL) {
p[0] = '_';
p++;
memmove(p, p + 1, strlen(p));
}
return out;
}