diff --git a/lib/librte_eal/common/eal_common_trace.c b/lib/librte_eal/common/eal_common_trace.c index 923b1dc125..43b1d4d7ab 100644 --- a/lib/librte_eal/common/eal_common_trace.c +++ b/lib/librte_eal/common/eal_common_trace.c @@ -16,6 +16,7 @@ #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); @@ -37,6 +38,9 @@ trace_list_head_get(void) 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; @@ -85,6 +89,7 @@ eal_trace_fini(void) { if (!rte_trace_is_enabled()) return; + trace_mem_per_thread_free(); trace_metadata_destroy(); } @@ -227,6 +232,95 @@ rte_trace_point_lookup(const char *name) 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)) diff --git a/lib/librte_eal/common/eal_common_trace_utils.c b/lib/librte_eal/common/eal_common_trace_utils.c index 6b43802203..503d0ab3d9 100644 --- a/lib/librte_eal/common/eal_common_trace_utils.c +++ b/lib/librte_eal/common/eal_common_trace_utils.c @@ -14,6 +14,26 @@ #include "eal_filesystem.h" #include "eal_trace.h" +const char * +trace_mode_to_string(enum rte_trace_mode mode) +{ + switch (mode) { + case RTE_TRACE_MODE_OVERWRITE: return "overwrite"; + case RTE_TRACE_MODE_DISCARD: return "discard"; + default: return "unknown"; + } +} + +const char * +trace_area_to_string(enum trace_area_e area) +{ + switch (area) { + case TRACE_AREA_HEAP: return "heap"; + case TRACE_AREA_HUGEPAGE: return "hugepage"; + default: return "unknown"; + } +} + static bool trace_entry_compare(const char *name) { diff --git a/lib/librte_eal/common/eal_trace.h b/lib/librte_eal/common/eal_trace.h index f8d75bbfee..846677cada 100644 --- a/lib/librte_eal/common/eal_trace.h +++ b/lib/librte_eal/common/eal_trace.h @@ -6,11 +6,16 @@ #define __EAL_TRACE_H #include +#include +#include #include #include #include #include +#include "eal_private.h" +#include "eal_thread.h" + #define trace_err(fmt, args...) \ RTE_LOG(ERR, EAL, "%s():%u " fmt "\n", __func__, __LINE__, ## args) @@ -21,6 +26,8 @@ #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; @@ -29,6 +36,16 @@ struct trace_point { 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; @@ -38,6 +55,8 @@ struct trace { 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; @@ -57,6 +76,12 @@ trace_id_get(rte_trace_point_t *trace) __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); @@ -65,12 +90,15 @@ STAILQ_HEAD(trace_point_head, trace_point); 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); diff --git a/lib/librte_eal/include/rte_trace_point.h b/lib/librte_eal/include/rte_trace_point.h index 89f384db30..fc3d9c4f5d 100644 --- a/lib/librte_eal/include/rte_trace_point.h +++ b/lib/librte_eal/include/rte_trace_point.h @@ -227,6 +227,15 @@ __rte_trace_point_fp_is_enabled(void) #endif } +/** + * @internal + * + * Allocate trace memory buffer per thread. + * + */ +__rte_experimental +void __rte_trace_mem_per_thread_alloc(void); + /** * @internal * diff --git a/lib/librte_eal/include/rte_trace_point_provider.h b/lib/librte_eal/include/rte_trace_point_provider.h index 45a113c0d1..b8d727387f 100644 --- a/lib/librte_eal/include/rte_trace_point_provider.h +++ b/lib/librte_eal/include/rte_trace_point_provider.h @@ -9,6 +9,10 @@ #ifndef _RTE_TRACE_POINT_PROVIDER_H_ #define _RTE_TRACE_POINT_PROVIDER_H_ +#include +#include +#include + #define __RTE_TRACE_EVENT_HEADER_ID_SHIFT (48) #define __RTE_TRACE_FIELD_SIZE_SHIFT 0 @@ -18,4 +22,20 @@ #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_ */ diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index 2e6aacc17e..98e0f8413f 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -337,7 +337,9 @@ EXPERIMENTAL { rte_thread_is_intr; # added in 20.05 + __rte_trace_mem_per_thread_alloc; __rte_trace_point_register; + per_lcore_trace_mem; per_lcore_trace_point_sz; rte_log_can_log; rte_thread_getname;