On Thu, Mar 19, 2020 at 3:33 PM Mattias Rönnblom
<mattias.ronnb...@ericsson.com> wrote:
>
> On 2020-03-18 20:02, jer...@marvell.com wrote:
> > From: Jerin Jacob <jer...@marvell.com>
> >

> > +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.

OK. I will change to "register_fn" in v2.


> > +{
> > +     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.

The reason for keeping level as uint32_t to keep compatibility
with rte_log level datatype. For some reason, rte_log defined level
as uint32_t, So I thought of sticking to that so that we can migrate the
rte_log to rte_trace in future if needed and also making semantics
similar to rte_log.

>
> > +             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?

This been called by the constructor at that time memory
services are not enabled and it is for the per-process like rte_log
scheme.


> > +     if (tp == NULL) {
> > +             trace_err("fail to allocate trace point memory");
> > +             rte_errno = ENOMEM; goto fail;
> Missing newline.

I will fix it in v2.

> > +     }
> > +
> > +     /* 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.

I thought that initially, Two reasons why I did not do that
1) The flags have been used in fastpath, I prefer to work with flags
in fastpath so that
there is no performance impact using bitfields from the compiler _if any_.
2) In some of the places, I can simply operate on APIs like
__atomic_and_fetch() with flags.

Reply via email to