#include "eal_trace.h"
RTE_DEFINE_PER_LCORE(volatile int, trace_point_sz);
+RTE_DEFINE_PER_LCORE(void *, trace_mem);
static RTE_DEFINE_PER_LCORE(char, ctf_field[TRACE_CTF_FIELD_SIZE]);
static RTE_DEFINE_PER_LCORE(int, ctf_count);
int
eal_trace_init(void)
{
+ /* Trace memory should start with 8B aligned for natural alignment */
+ RTE_BUILD_BUG_ON((offsetof(struct __rte_trace_header, mem) % 8) != 0);
+
/* One of the trace point registration failed */
if (trace.register_errno) {
rte_errno = trace.register_errno;
{
if (!rte_trace_is_enabled())
return;
+ trace_mem_per_thread_free();
trace_metadata_destroy();
}
return NULL;
}
+void
+__rte_trace_mem_per_thread_alloc(void)
+{
+ struct trace *trace = trace_obj_get();
+ struct __rte_trace_header *header;
+ uint32_t count;
+
+ if (!rte_trace_is_enabled())
+ return;
+
+ if (RTE_PER_LCORE(trace_mem))
+ return;
+
+ rte_spinlock_lock(&trace->lock);
+
+ count = trace->nb_trace_mem_list;
+
+ /* Allocate room for storing the thread trace mem meta */
+ trace->lcore_meta = realloc(trace->lcore_meta,
+ sizeof(trace->lcore_meta[0]) * (count + 1));
+
+ /* Provide dummy space for fast path to consume */
+ if (trace->lcore_meta == NULL) {
+ trace_crit("trace mem meta memory realloc failed");
+ header = NULL;
+ goto fail;
+ }
+
+ /* First attempt from huge page */
+ header = rte_malloc(NULL, trace_mem_sz(trace->buff_len), 8);
+ if (header) {
+ trace->lcore_meta[count].area = TRACE_AREA_HUGEPAGE;
+ goto found;
+ }
+
+ /* Second attempt from heap */
+ header = malloc(trace_mem_sz(trace->buff_len));
+ if (header == NULL) {
+ trace_crit("trace mem malloc attempt failed");
+ header = NULL;
+ goto fail;
+
+ }
+
+ /* Second attempt from heap is success */
+ trace->lcore_meta[count].area = TRACE_AREA_HEAP;
+
+ /* Initialize the trace header */
+found:
+ header->offset = 0;
+ header->len = trace->buff_len;
+ header->stream_header.magic = TRACE_CTF_MAGIC;
+ rte_uuid_copy(header->stream_header.uuid, trace->uuid);
+ header->stream_header.lcore_id = rte_lcore_id();
+
+ /* Store the thread name */
+ char *name = header->stream_header.thread_name;
+ memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
+ rte_thread_getname(pthread_self(), name,
+ __RTE_TRACE_EMIT_STRING_LEN_MAX);
+
+ trace->lcore_meta[count].mem = header;
+ trace->nb_trace_mem_list++;
+fail:
+ RTE_PER_LCORE(trace_mem) = header;
+ rte_spinlock_unlock(&trace->lock);
+}
+
+void
+trace_mem_per_thread_free(void)
+{
+ struct trace *trace = trace_obj_get();
+ uint32_t count;
+ void *mem;
+
+ if (!rte_trace_is_enabled())
+ return;
+
+ rte_spinlock_lock(&trace->lock);
+ for (count = 0; count < trace->nb_trace_mem_list; count++) {
+ mem = trace->lcore_meta[count].mem;
+ if (trace->lcore_meta[count].area == TRACE_AREA_HUGEPAGE)
+ rte_free(mem);
+ else if (trace->lcore_meta[count].area == TRACE_AREA_HEAP)
+ free(mem);
+ }
+ rte_spinlock_unlock(&trace->lock);
+}
+
int
__rte_trace_point_register(rte_trace_point_t *handle, const char *name,
void (*register_fn)(void))
#define __EAL_TRACE_H
#include <rte_cycles.h>
+#include <rte_log.h>
+#include <rte_malloc.h>
#include <rte_spinlock.h>
#include <rte_trace.h>
#include <rte_trace_point.h>
#include <rte_uuid.h>
+#include "eal_private.h"
+#include "eal_thread.h"
+
#define trace_err(fmt, args...) \
RTE_LOG(ERR, EAL, "%s():%u " fmt "\n", __func__, __LINE__, ## args)
#define TRACE_DIR_STR_LEN (sizeof("YYYY-mm-dd-AM-HH-MM-SS") + TRACE_PREFIX_LEN)
#define TRACE_CTF_FIELD_SIZE 384
#define TRACE_POINT_NAME_SIZE 64
+#define TRACE_CTF_MAGIC 0xC1FC1FC1
+
struct trace_point {
STAILQ_ENTRY(trace_point) next;
char ctf_field[TRACE_CTF_FIELD_SIZE];
};
+enum trace_area_e {
+ TRACE_AREA_HEAP,
+ TRACE_AREA_HUGEPAGE,
+};
+
+struct thread_mem_meta {
+ void *mem;
+ enum trace_area_e area;
+};
+
struct trace {
char dir[PATH_MAX];
int dir_offset;
rte_uuid_t uuid;
uint32_t buff_len;
uint32_t nb_trace_points;
+ uint32_t nb_trace_mem_list;
+ struct thread_mem_meta *lcore_meta;
uint64_t epoch_sec;
uint64_t epoch_nsec;
uint64_t uptime_ticks;
__RTE_TRACE_FIELD_ID_SHIFT;
}
+static inline size_t
+trace_mem_sz(uint32_t len)
+{
+ return len + sizeof(struct __rte_trace_header);
+}
+
/* Trace object functions */
struct trace *trace_obj_get(void);
struct trace_point_head *trace_list_head_get(void);
/* Util functions */
+const char *trace_mode_to_string(enum rte_trace_mode mode);
+const char *trace_area_to_string(enum trace_area_e area);
bool trace_has_duplicate_entry(void);
void trace_uuid_generate(void);
int trace_metadata_create(void);
void trace_metadata_destroy(void);
int trace_mkdir(void);
int trace_epoch_time_save(void);
+void trace_mem_per_thread_free(void);
/* EAL interface */
int eal_trace_init(void);
#ifndef _RTE_TRACE_POINT_PROVIDER_H_
#define _RTE_TRACE_POINT_PROVIDER_H_
+#include <rte_per_lcore.h>
+#include <rte_string_fns.h>
+#include <rte_uuid.h>
+
#define __RTE_TRACE_EVENT_HEADER_ID_SHIFT (48)
#define __RTE_TRACE_FIELD_SIZE_SHIFT 0
#define __RTE_TRACE_FIELD_ENABLE_MASK (1ULL << 63)
#define __RTE_TRACE_FIELD_ENABLE_DISCARD (1ULL << 62)
+struct __rte_trace_stream_header {
+ uint32_t magic;
+ rte_uuid_t uuid;
+ uint32_t lcore_id;
+ char thread_name[__RTE_TRACE_EMIT_STRING_LEN_MAX];
+} __rte_packed;
+
+struct __rte_trace_header {
+ uint32_t offset;
+ uint32_t len;
+ struct __rte_trace_stream_header stream_header;
+ uint8_t mem[];
+};
+
+RTE_DECLARE_PER_LCORE(void *, trace_mem);
+
#endif /* _RTE_TRACE_POINT_PROVIDER_H_ */