On 2020-03-18 20:02, jer...@marvell.com wrote:
> From: Jerin Jacob <jer...@marvell.com>
>
> The consumers of trace API defines the tracepoint and registers
> to eal. Internally these tracepoints will be stored in STAILQ
> for future use. This patch implements the tracepoint
> registration function.
>
> Signed-off-by: Jerin Jacob <jer...@marvell.com>
> ---
>   MAINTAINERS                                   |   1 +
>   lib/librte_eal/common/Makefile                |   2 +-
>   lib/librte_eal/common/eal_common_trace.c      | 107 +++++++++++++++++-
>   lib/librte_eal/common/eal_trace.h             |  36 ++++++
>   lib/librte_eal/common/include/rte_trace.h     |  29 +++++
>   .../common/include/rte_trace_provider.h       |  24 ++++
>   .../common/include/rte_trace_register.h       |  20 ++++
>   lib/librte_eal/common/meson.build             |   2 +
>   lib/librte_eal/rte_eal_version.map            |   1 +
>   9 files changed, 220 insertions(+), 2 deletions(-)
>   create mode 100644 lib/librte_eal/common/eal_trace.h
>   create mode 100644 lib/librte_eal/common/include/rte_trace_provider.h
>   create mode 100644 lib/librte_eal/common/include/rte_trace_register.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 63d85c7da..452fd2c4f 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -201,6 +201,7 @@ M: Jerin Jacob <jer...@marvell.com>
>   M: Sunil Kumar Kori <sk...@marvell.com>
>   F: lib/librte_eal/common/include/rte_trace*.h
>   F: lib/librte_eal/common/eal_common_trace*.c
> +F: lib/librte_eal/common/eal_trace.h
>   
>   Memory Allocation
>   M: Anatoly Burakov <anatoly.bura...@intel.com>
> diff --git a/lib/librte_eal/common/Makefile b/lib/librte_eal/common/Makefile
> index 9384d6f6e..8f2f25c1d 100644
> --- a/lib/librte_eal/common/Makefile
> +++ b/lib/librte_eal/common/Makefile
> @@ -9,7 +9,7 @@ INC += rte_debug.h rte_eal.h rte_eal_interrupts.h
>   INC += rte_errno.h rte_launch.h rte_lcore.h
>   INC += rte_log.h rte_memory.h rte_memzone.h
>   INC += rte_per_lcore.h rte_random.h
> -INC += rte_trace.h
> +INC += rte_trace.h rte_trace_provider.h rte_trace_register.h
>   INC += rte_tailq.h rte_interrupts.h rte_alarm.h
>   INC += rte_string_fns.h rte_version.h
>   INC += rte_eal_memconfig.h
> diff --git a/lib/librte_eal/common/eal_common_trace.c 
> b/lib/librte_eal/common/eal_common_trace.c
> index e18ba1c95..ddde04de5 100644
> --- a/lib/librte_eal/common/eal_common_trace.c
> +++ b/lib/librte_eal/common/eal_common_trace.c
> @@ -2,5 +2,110 @@
>    * Copyright(C) 2020 Marvell International Ltd.
>    */
>   
> -#include <rte_trace.h>
> +#include <inttypes.h>
> +#include <sys/queue.h>
>   
> +#include <rte_common.h>
> +#include <rte_errno.h>
> +#include <rte_lcore.h>
> +#include <rte_per_lcore.h>
> +#include <rte_string_fns.h>
> +
> +#include "eal_trace.h"
> +
> +RTE_DEFINE_PER_LCORE(volatile int, trace_point_sz);
> +RTE_DEFINE_PER_LCORE(char, ctf_field[TRACE_CTF_FIELD_SIZE]);
> +RTE_DEFINE_PER_LCORE(int, ctf_count);
> +
> +static struct trace_point_head tp_list = STAILQ_HEAD_INITIALIZER(tp_list);
> +static struct trace trace;
> +
> +int
> +__rte_trace_point_register(rte_trace_t handle, const char *name, uint32_t 
> level,
> +                      void (*fn)(void))
Maybe a more descriptive name than 'fn' would be in order.
> +{
> +     char *field = RTE_PER_LCORE(ctf_field);
> +     struct trace_point *tp;
> +     uint16_t sz;
> +
> +     /* Sanity checks of arguments */
> +     if (name == NULL || fn == NULL || handle == NULL) {
> +             trace_err("invalid arguments");
> +             rte_errno = EINVAL; goto fail;
> +     }
> +
> +     /* Sanity check of level */
> +     if (level > RTE_LOG_DEBUG || level > UINT8_MAX) {

Consider a #define for the max level. If the type was uint8_t, you 
wouldn't need to check max at all.

> +             trace_err("invalid log level=%d", level);
> +             rte_errno = EINVAL; goto fail;
> +
> +     }
> +
> +     /* Check the size of the trace point object */
> +     RTE_PER_LCORE(trace_point_sz) = 0;
> +     RTE_PER_LCORE(ctf_count) = 0;
> +     fn();
> +     if (RTE_PER_LCORE(trace_point_sz) == 0) {
> +             trace_err("missing rte_trace_emit_header() in register fn");
> +             rte_errno = EBADF; goto fail;
> +     }
> +
> +     /* Is size overflowed */
> +     if (RTE_PER_LCORE(trace_point_sz) > UINT16_MAX) {
> +             trace_err("trace point size overflowed");
> +             rte_errno = ENOSPC; goto fail;
> +     }
> +
> +     /* Are we running out of space to store trace points? */
> +     if (trace.nb_trace_points > UINT16_MAX) {
> +             trace_err("trace point exceeds the max count");
> +             rte_errno = ENOSPC; goto fail;
> +     }
> +
> +     /* Get the size of the trace point */
> +     sz = RTE_PER_LCORE(trace_point_sz);
> +     tp = calloc(1, sizeof(struct trace_point));
Not rte_zmalloc()? Are secondary processes accessing this memory?
> +     if (tp == NULL) {
> +             trace_err("fail to allocate trace point memory");
> +             rte_errno = ENOMEM; goto fail;
Missing newline.
> +     }
> +
> +     /* Initialize the trace point */
> +     if (rte_strscpy(tp->name, name, TRACE_POINT_NAME_SIZE) < 0) {
> +             trace_err("name is too long");
> +             rte_errno = E2BIG;
> +             goto free;
> +     }
> +
> +     /* Copy the field data for future use */
> +     if (rte_strscpy(tp->ctf_field, field, TRACE_CTF_FIELD_SIZE) < 0) {
> +             trace_err("CTF field size is too long");
> +             rte_errno = E2BIG;
> +             goto free;
> +     }
> +
> +     /* Clear field memory for the next event */
> +     memset(field, 0, TRACE_CTF_FIELD_SIZE);
> +
> +     /* Form the trace handle */
> +     *handle = sz;
> +     *handle |= trace.nb_trace_points << __RTE_TRACE_FIELD_ID_SHIFT;
> +     *handle |= (uint64_t)level << __RTE_TRACE_FIELD_LEVEL_SHIFT;
If *handle would be a struct, you could use a bitfield instead, and much 
simplify this code.
> +
> +     trace.nb_trace_points++;
> +     tp->handle = handle;
> +
> +     /* Add the trace point at tail */
> +     STAILQ_INSERT_TAIL(&tp_list, tp, next);
> +     __atomic_thread_fence(__ATOMIC_RELEASE);
> +
> +     /* All Good !!! */
> +     return 0;
> +free:
> +     free(tp);
> +fail:
> +     if (trace.register_errno == 0)
> +             trace.register_errno = rte_errno;
> +
> +     return -rte_errno;
> +}
> diff --git a/lib/librte_eal/common/eal_trace.h 
> b/lib/librte_eal/common/eal_trace.h
> new file mode 100644
> index 000000000..9aef536a0
> --- /dev/null
> +++ b/lib/librte_eal/common/eal_trace.h
> @@ -0,0 +1,36 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2020 Marvell International Ltd.
> + */
> +
> +#ifndef __EAL_TRACE_H
> +#define __EAL_TRACE_H
> +
> +#include <rte_trace.h>
> +
> +#define trace_err(fmt, args...)\
> +     RTE_LOG(ERR, EAL, "%s():%u " fmt "\n",\
> +             __func__, __LINE__, ## args)
> +
> +#define trace_crit(fmt, args...)\
> +     RTE_LOG(CRIT, EAL, "%s():%u " fmt "\n",\
> +             __func__, __LINE__, ## args)
> +
> +#define TRACE_CTF_FIELD_SIZE 384
> +#define TRACE_POINT_NAME_SIZE 64
> +
> +struct trace_point {
> +     STAILQ_ENTRY(trace_point) next;
> +     rte_trace_t handle;
> +     char name[TRACE_POINT_NAME_SIZE];
> +     char ctf_field[TRACE_CTF_FIELD_SIZE];
> +};
> +
> +struct trace {
> +     int register_errno;
> +     uint32_t nb_trace_points;
> +};
> +
> +/* Trace point list functions */
> +STAILQ_HEAD(trace_point_head, trace_point);
> +
> +#endif /* __EAL_TRACE_H */
> diff --git a/lib/librte_eal/common/include/rte_trace.h 
> b/lib/librte_eal/common/include/rte_trace.h
> index d008b64f1..da70dfdbb 100644
> --- a/lib/librte_eal/common/include/rte_trace.h
> +++ b/lib/librte_eal/common/include/rte_trace.h
> @@ -518,6 +518,35 @@ _tp _args \
>   
>   #endif /* __DOXYGEN__ */
>   
> +/**
> + * @internal @warning
> + * @b EXPERIMENTAL: this API may change without prior notice
> + *
> + * Helper function to register a dynamic tracepoint.
> + * Use RTE_TRACE_POINT_REGISTER() macro for tracepoint registration.
> + *
> + * @param trace
> + *   The tracepoint object created using RTE_TRACE_POINT_DEFINE().
> + * @param name
> + *   The name of the tracepoint object.
> + * @param level
> + *   Trace level. A value between RTE_LOG_EMERG (1) and RTE_LOG_DEBUG (8).
> + * @param f
> + *   Trace registration function.
> + * @return
> + *   - 0: Successfully registered the tracepoint.
> + *   - <0: Failure to register the tracepoint.
> + */
> +__rte_experimental
> +int __rte_trace_point_register(rte_trace_t trace, const char *name,
> +                          uint32_t level, void (*fn)(void));
> +
> +#ifdef RTE_TRACE_POINT_REGISTER_SELECT
> +#include <rte_trace_register.h>
> +#else
> +#include <rte_trace_provider.h>
> +#endif
> +
>   #ifdef __cplusplus
>   }
>   #endif
> diff --git a/lib/librte_eal/common/include/rte_trace_provider.h 
> b/lib/librte_eal/common/include/rte_trace_provider.h
> new file mode 100644
> index 000000000..b4da87ba1
> --- /dev/null
> +++ b/lib/librte_eal/common/include/rte_trace_provider.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2020 Marvell International Ltd.
> + */
> +
> +#ifndef _RTE_TRACE_H_
> +#error do not include this file directly, use <rte_trace.h> instead
> +#endif
> +
> +#ifndef _RTE_TRACE_PROVIDER_H_
> +#define _RTE_TRACE_PROVIDER_H_
> +
> +#define __RTE_TRACE_EVENT_HEADER_ID_SHIFT (48)
> +
> +#define __RTE_TRACE_FIELD_ENABLE_MASK (1ULL << 63)
> +#define __RTE_TRACE_FIELD_ENABLE_DISCARD (1ULL << 62)
> +#define __RTE_TRACE_FIELD_SIZE_SHIFT 0
> +#define __RTE_TRACE_FIELD_SIZE_MASK (0xffffULL << 
> __RTE_TRACE_FIELD_SIZE_SHIFT)
> +#define __RTE_TRACE_FIELD_ID_SHIFT (16)
> +#define __RTE_TRACE_FIELD_ID_MASK (0xffffULL << __RTE_TRACE_FIELD_ID_SHIFT)
> +#define __RTE_TRACE_FIELD_LEVEL_SHIFT (32)
> +#define __RTE_TRACE_FIELD_LEVEL_MASK (0xffULL << 
> __RTE_TRACE_FIELD_LEVEL_SHIFT)
> +
> +
> +#endif /* _RTE_TRACE_PROVIDER_H_ */
> diff --git a/lib/librte_eal/common/include/rte_trace_register.h 
> b/lib/librte_eal/common/include/rte_trace_register.h
> new file mode 100644
> index 000000000..e9940b414
> --- /dev/null
> +++ b/lib/librte_eal/common/include/rte_trace_register.h
> @@ -0,0 +1,20 @@
> +/* SPDX-License-Identifier: BSD-3-Clause
> + * Copyright(C) 2020 Marvell International Ltd.
> + */
> +
> +#ifndef _RTE_TRACE_H_
> +#error do not include this file directly, use <rte_trace.h> instead
> +#endif
> +
> +#ifndef _RTE_TRACE_REGISTER_H_
> +#define _RTE_TRACE_REGISTER_H_
> +
> +#include <rte_per_lcore.h>
> +
> +RTE_DECLARE_PER_LCORE(volatile int, trace_point_sz);
> +
> +#define RTE_TRACE_POINT_REGISTER(trace, name, level)\
> +     __rte_trace_point_register(&__##trace, RTE_STR(name),\
> +                     RTE_LOG_ ## level, (void (*)(void)) trace)
> +
> +#endif /* _RTE_TRACE_REGISTER_H_ */
> diff --git a/lib/librte_eal/common/meson.build 
> b/lib/librte_eal/common/meson.build
> index 30fb9b85f..88c14ebe5 100644
> --- a/lib/librte_eal/common/meson.build
> +++ b/lib/librte_eal/common/meson.build
> @@ -86,6 +86,8 @@ common_headers = files(
>       'include/rte_string_fns.h',
>       'include/rte_tailq.h',
>       'include/rte_trace.h',
> +     'include/rte_trace_provider.h',
> +     'include/rte_trace_register.h',
>       'include/rte_time.h',
>       'include/rte_uuid.h',
>       'include/rte_version.h',
> diff --git a/lib/librte_eal/rte_eal_version.map 
> b/lib/librte_eal/rte_eal_version.map
> index cadfa6465..d97d14845 100644
> --- a/lib/librte_eal/rte_eal_version.map
> +++ b/lib/librte_eal/rte_eal_version.map
> @@ -338,4 +338,5 @@ EXPERIMENTAL {
>   
>       # added in 20.05
>       rte_thread_getname;
> +     __rte_trace_point_register;
>   };


Reply via email to