LCOV - code coverage report
Current view: top level - lib/eal/common - eal_common_trace.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 179 226 79.2 %
Date: 2025-05-01 17:49:45 Functions: 23 23 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 75 118 63.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(C) 2020 Marvell International Ltd.
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdlib.h>
       6                 :            : #include <fnmatch.h>
       7                 :            : #include <pthread.h>
       8                 :            : #include <sys/queue.h>
       9                 :            : #include <regex.h>
      10                 :            : 
      11                 :            : #include <rte_common.h>
      12                 :            : #include <rte_errno.h>
      13                 :            : #include <rte_lcore.h>
      14                 :            : #include <rte_per_lcore.h>
      15                 :            : #include <rte_string_fns.h>
      16                 :            : 
      17                 :            : #include <eal_export.h>
      18                 :            : #include "eal_trace.h"
      19                 :            : 
      20                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(per_lcore_trace_point_sz, 20.05)
      21                 :            : RTE_DEFINE_PER_LCORE(volatile int, trace_point_sz);
      22                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(per_lcore_trace_mem, 20.05)
      23                 :            : RTE_DEFINE_PER_LCORE(void *, trace_mem);
      24                 :            : static RTE_DEFINE_PER_LCORE(char *, ctf_field);
      25                 :            : 
      26                 :            : static struct trace_point_head tp_list = STAILQ_HEAD_INITIALIZER(tp_list);
      27                 :            : static struct trace trace = { .args = STAILQ_HEAD_INITIALIZER(trace.args), };
      28                 :            : 
      29                 :            : struct trace *
      30                 :       2950 : trace_obj_get(void)
      31                 :            : {
      32                 :       2950 :         return &trace;
      33                 :            : }
      34                 :            : 
      35                 :            : struct trace_point_head *
      36                 :     106467 : trace_list_head_get(void)
      37                 :            : {
      38                 :     106467 :         return &tp_list;
      39                 :            : }
      40                 :            : 
      41                 :            : int
      42                 :        199 : eal_trace_init(void)
      43                 :            : {
      44                 :            :         struct trace_arg *arg;
      45                 :            : 
      46                 :            :         /* Trace memory should start with 8B aligned for natural alignment */
      47                 :            :         RTE_BUILD_BUG_ON((offsetof(struct __rte_trace_header, mem) % 8) != 0);
      48                 :            : 
      49                 :            :         /* One of the trace point registration failed */
      50         [ -  + ]:        199 :         if (trace.register_errno) {
      51                 :          0 :                 rte_errno = trace.register_errno;
      52                 :          0 :                 goto fail;
      53                 :            :         }
      54                 :            : 
      55                 :            :         rte_spinlock_init(&trace.lock);
      56                 :            : 
      57                 :            :         /* Is duplicate trace name registered */
      58         [ -  + ]:        199 :         if (trace_has_duplicate_entry())
      59                 :          0 :                 goto fail;
      60                 :            : 
      61                 :            :         /* Generate UUID ver 4 with total size of events and number of
      62                 :            :          * events
      63                 :            :          */
      64                 :        199 :         trace_uuid_generate();
      65                 :            : 
      66                 :            :         /* Apply buffer size configuration for trace output */
      67                 :        199 :         trace_bufsz_args_apply();
      68                 :            : 
      69                 :            :         /* Generate CTF TDSL metadata */
      70         [ -  + ]:        199 :         if (trace_metadata_create() < 0)
      71                 :          0 :                 goto fail;
      72                 :            : 
      73                 :            :         /* Save current epoch timestamp for future use */
      74         [ -  + ]:        199 :         if (trace_epoch_time_save() < 0)
      75                 :          0 :                 goto free_meta;
      76                 :            : 
      77                 :            :         /* Apply global configurations */
      78         [ +  + ]:        200 :         STAILQ_FOREACH(arg, &trace.args, next)
      79                 :          1 :                 trace_args_apply(arg->val);
      80                 :            : 
      81                 :        199 :         rte_trace_mode_set(trace.mode);
      82                 :            : 
      83                 :        199 :         return 0;
      84                 :            : 
      85                 :            : free_meta:
      86                 :          0 :         trace_metadata_destroy();
      87                 :          0 : fail:
      88                 :          0 :         trace_err("failed to initialize trace [%s]", rte_strerror(rte_errno));
      89                 :          0 :         return -rte_errno;
      90                 :            : }
      91                 :            : 
      92                 :            : void
      93                 :        252 : eal_trace_fini(void)
      94                 :            : {
      95                 :        252 :         trace_mem_free();
      96                 :        252 :         trace_metadata_destroy();
      97                 :        252 :         eal_trace_args_free();
      98                 :        252 : }
      99                 :            : 
     100                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_is_enabled, 20.05)
     101                 :            : bool
     102                 :        805 : rte_trace_is_enabled(void)
     103                 :            : {
     104                 :        805 :         return rte_atomic_load_explicit(&trace.status, rte_memory_order_acquire) != 0;
     105                 :            : }
     106                 :            : 
     107                 :            : static void
     108                 :     243124 : trace_mode_set(rte_trace_point_t *t, enum rte_trace_mode mode)
     109                 :            : {
     110         [ +  + ]:     243124 :         if (mode == RTE_TRACE_MODE_OVERWRITE)
     111                 :     242060 :                 rte_atomic_fetch_and_explicit(t, ~__RTE_TRACE_FIELD_ENABLE_DISCARD,
     112                 :            :                         rte_memory_order_release);
     113                 :            :         else
     114                 :       1064 :                 rte_atomic_fetch_or_explicit(t, __RTE_TRACE_FIELD_ENABLE_DISCARD,
     115                 :            :                         rte_memory_order_release);
     116                 :     243124 : }
     117                 :            : 
     118                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_mode_set, 20.05)
     119                 :            : void
     120                 :        205 : rte_trace_mode_set(enum rte_trace_mode mode)
     121                 :            : {
     122                 :            :         struct trace_point *tp;
     123                 :            : 
     124         [ +  + ]:     109265 :         STAILQ_FOREACH(tp, &tp_list, next)
     125                 :     109060 :                 trace_mode_set(tp->handle, mode);
     126                 :            : 
     127                 :        205 :         trace.mode = mode;
     128                 :        205 : }
     129                 :            : 
     130                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_mode_get, 20.05)
     131                 :            : enum
     132                 :          8 : rte_trace_mode rte_trace_mode_get(void)
     133                 :            : {
     134                 :          8 :         return trace.mode;
     135                 :            : }
     136                 :            : 
     137                 :            : static bool
     138                 :            : trace_point_is_invalid(rte_trace_point_t *t)
     139                 :            : {
     140   [ -  +  -  +  :       1628 :         return (t == NULL) || (trace_id_get(t) >= trace.nb_trace_points);
                   -  + ]
     141                 :            : }
     142                 :            : 
     143                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_is_enabled, 20.05)
     144                 :            : bool
     145         [ +  - ]:       1076 : rte_trace_point_is_enabled(rte_trace_point_t *t)
     146                 :            : {
     147                 :            :         uint64_t val;
     148                 :            : 
     149         [ +  - ]:       1076 :         if (trace_point_is_invalid(t))
     150                 :            :                 return false;
     151                 :            : 
     152                 :       1076 :         val = rte_atomic_load_explicit(t, rte_memory_order_acquire);
     153                 :       1076 :         return (val & __RTE_TRACE_FIELD_ENABLE_MASK) != 0;
     154                 :            : }
     155                 :            : 
     156                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_enable, 20.05)
     157                 :            : int
     158         [ +  - ]:        542 : rte_trace_point_enable(rte_trace_point_t *t)
     159                 :            : {
     160                 :            :         uint64_t prev;
     161                 :            : 
     162         [ +  - ]:        542 :         if (trace_point_is_invalid(t))
     163                 :            :                 return -ERANGE;
     164                 :            : 
     165                 :        542 :         prev = rte_atomic_fetch_or_explicit(t, __RTE_TRACE_FIELD_ENABLE_MASK,
     166                 :            :                 rte_memory_order_release);
     167         [ +  - ]:        542 :         if ((prev & __RTE_TRACE_FIELD_ENABLE_MASK) == 0)
     168                 :        542 :                 rte_atomic_fetch_add_explicit(&trace.status, 1, rte_memory_order_release);
     169                 :            :         return 0;
     170                 :            : }
     171                 :            : 
     172                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_disable, 20.05)
     173                 :            : int
     174         [ +  - ]:         10 : rte_trace_point_disable(rte_trace_point_t *t)
     175                 :            : {
     176                 :            :         uint64_t prev;
     177                 :            : 
     178         [ +  - ]:         10 :         if (trace_point_is_invalid(t))
     179                 :            :                 return -ERANGE;
     180                 :            : 
     181                 :         10 :         prev = rte_atomic_fetch_and_explicit(t, ~__RTE_TRACE_FIELD_ENABLE_MASK,
     182                 :            :                 rte_memory_order_release);
     183         [ +  + ]:         10 :         if ((prev & __RTE_TRACE_FIELD_ENABLE_MASK) != 0)
     184                 :          8 :                 rte_atomic_fetch_sub_explicit(&trace.status, 1, rte_memory_order_release);
     185                 :            :         return 0;
     186                 :            : }
     187                 :            : 
     188                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_pattern, 20.05)
     189                 :            : int
     190                 :          6 : rte_trace_pattern(const char *pattern, bool enable)
     191                 :            : {
     192                 :            :         struct trace_point *tp;
     193                 :            :         int rc = 0, found = 0;
     194                 :            : 
     195         [ +  + ]:       3198 :         STAILQ_FOREACH(tp, &tp_list, next) {
     196         [ +  + ]:       3192 :                 if (fnmatch(pattern, tp->name, 0) != 0)
     197                 :       3184 :                         continue;
     198                 :            : 
     199         [ +  + ]:          8 :                 if (enable)
     200                 :          4 :                         rc = rte_trace_point_enable(tp->handle);
     201                 :            :                 else
     202                 :          4 :                         rc = rte_trace_point_disable(tp->handle);
     203         [ +  - ]:          8 :                 if (rc < 0) {
     204                 :            :                         found = 0;
     205                 :            :                         break;
     206                 :            :                 }
     207                 :            :                 found = 1;
     208                 :            :         }
     209                 :            : 
     210                 :          6 :         return rc | found;
     211                 :            : }
     212                 :            : 
     213                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_regexp, 20.05)
     214                 :            : int
     215                 :          7 : rte_trace_regexp(const char *regex, bool enable)
     216                 :            : {
     217                 :            :         struct trace_point *tp;
     218                 :            :         int rc = 0, found = 0;
     219                 :            :         regex_t r;
     220                 :            : 
     221         [ +  - ]:          7 :         if (regcomp(&r, regex, 0) != 0)
     222                 :            :                 return -EINVAL;
     223                 :            : 
     224         [ +  + ]:       3731 :         STAILQ_FOREACH(tp, &tp_list, next) {
     225         [ +  + ]:       3724 :                 if (regexec(&r, tp->name, 0, NULL, 0) != 0)
     226                 :       3184 :                         continue;
     227                 :            : 
     228         [ +  + ]:        540 :                 if (enable)
     229                 :        536 :                         rc = rte_trace_point_enable(tp->handle);
     230                 :            :                 else
     231                 :          4 :                         rc = rte_trace_point_disable(tp->handle);
     232         [ +  - ]:        540 :                 if (rc < 0) {
     233                 :            :                         found = 0;
     234                 :            :                         break;
     235                 :            :                 }
     236                 :            :                 found = 1;
     237                 :            :         }
     238                 :          7 :         regfree(&r);
     239                 :            : 
     240                 :          7 :         return rc | found;
     241                 :            : }
     242                 :            : 
     243                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_point_lookup, 20.05)
     244                 :            : rte_trace_point_t *
     245                 :          4 : rte_trace_point_lookup(const char *name)
     246                 :            : {
     247                 :            :         struct trace_point *tp;
     248                 :            : 
     249         [ +  - ]:          4 :         if (name == NULL)
     250                 :            :                 return NULL;
     251                 :            : 
     252         [ +  + ]:       1068 :         STAILQ_FOREACH(tp, &tp_list, next)
     253         [ +  + ]:       1066 :                 if (strcmp(tp->name, name) == 0)
     254                 :          2 :                         return tp->handle;
     255                 :            : 
     256                 :            :         return NULL;
     257                 :            : }
     258                 :            : 
     259                 :            : static void
     260                 :       1064 : trace_point_dump(FILE *f, struct trace_point *tp)
     261                 :            : {
     262                 :       1064 :         rte_trace_point_t *handle = tp->handle;
     263                 :            : 
     264         [ +  + ]:       1064 :         fprintf(f, "\tid %d, %s, size is %d, %s\n",
     265                 :            :                 trace_id_get(handle), tp->name,
     266                 :       1064 :                 (uint16_t)(*handle & __RTE_TRACE_FIELD_SIZE_MASK),
     267                 :       1064 :                 rte_trace_point_is_enabled(handle) ? "enabled" : "disabled");
     268                 :       1064 : }
     269                 :            : 
     270                 :            : static void
     271                 :          2 : trace_lcore_mem_dump(FILE *f)
     272                 :            : {
     273                 :          2 :         struct trace *trace = trace_obj_get();
     274                 :            :         struct __rte_trace_header *header;
     275                 :            :         uint32_t count;
     276                 :            : 
     277                 :          2 :         rte_spinlock_lock(&trace->lock);
     278         [ -  + ]:          2 :         if (trace->nb_trace_mem_list == 0)
     279                 :          0 :                 goto out;
     280                 :            :         fprintf(f, "nb_trace_mem_list = %d\n", trace->nb_trace_mem_list);
     281                 :            :         fprintf(f, "\nTrace mem info\n--------------\n");
     282         [ +  + ]:          7 :         for (count = 0; count < trace->nb_trace_mem_list; count++) {
     283                 :          5 :                 header = trace->lcore_meta[count].mem;
     284                 :          5 :                 fprintf(f, "\tid %d, mem=%p, area=%s, lcore_id=%d, name=%s\n",
     285                 :            :                 count, header,
     286                 :            :                 trace_area_to_string(trace->lcore_meta[count].area),
     287                 :            :                 header->stream_header.lcore_id,
     288                 :          5 :                 header->stream_header.thread_name);
     289                 :            :         }
     290                 :          2 : out:
     291                 :            :         rte_spinlock_unlock(&trace->lock);
     292                 :          2 : }
     293                 :            : 
     294                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_trace_dump, 20.05)
     295                 :            : void
     296                 :          2 : rte_trace_dump(FILE *f)
     297                 :            : {
     298                 :          2 :         struct trace_point_head *tp_list = trace_list_head_get();
     299                 :          2 :         struct trace *trace = trace_obj_get();
     300                 :            :         struct trace_point *tp;
     301                 :            : 
     302                 :            :         fprintf(f, "\nGlobal info\n-----------\n");
     303         [ -  + ]:          2 :         fprintf(f, "status = %s\n",
     304                 :          2 :                 rte_trace_is_enabled() ? "enabled" : "disabled");
     305                 :          2 :         fprintf(f, "mode = %s\n",
     306                 :            :                 trace_mode_to_string(rte_trace_mode_get()));
     307                 :          2 :         fprintf(f, "dir = %s\n", trace->dir);
     308                 :          2 :         fprintf(f, "buffer len = %d\n", trace->buff_len);
     309                 :          2 :         fprintf(f, "number of trace points = %d\n", trace->nb_trace_points);
     310                 :            : 
     311                 :          2 :         trace_lcore_mem_dump(f);
     312                 :            :         fprintf(f, "\nTrace point info\n----------------\n");
     313         [ +  + ]:       1066 :         STAILQ_FOREACH(tp, tp_list, next)
     314                 :       1064 :                 trace_point_dump(f, tp);
     315                 :          2 : }
     316                 :            : 
     317                 :            : static void
     318                 :            : thread_get_name(rte_thread_t id, char *name, size_t len)
     319                 :            : {
     320                 :            : #if defined(RTE_EXEC_ENV_LINUX) && defined(__GLIBC__) && defined(__GLIBC_PREREQ)
     321                 :            : #if __GLIBC_PREREQ(2, 12)
     322                 :          5 :         pthread_getname_np((pthread_t)id.opaque_id, name, len);
     323                 :            : #endif
     324                 :            : #endif
     325                 :            :         RTE_SET_USED(id);
     326                 :            :         RTE_SET_USED(name);
     327                 :            :         RTE_SET_USED(len);
     328                 :            : }
     329                 :            : 
     330                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(__rte_trace_mem_per_thread_alloc, 20.05)
     331                 :            : void
     332                 :        803 : __rte_trace_mem_per_thread_alloc(void)
     333                 :            : {
     334                 :        803 :         struct trace *trace = trace_obj_get();
     335                 :            :         struct __rte_trace_header *header;
     336                 :            :         uint32_t count;
     337                 :            : 
     338         [ +  + ]:        803 :         if (!rte_trace_is_enabled())
     339                 :            :                 return;
     340                 :            : 
     341         [ +  - ]:          5 :         if (RTE_PER_LCORE(trace_mem))
     342                 :            :                 return;
     343                 :            : 
     344                 :          5 :         rte_spinlock_lock(&trace->lock);
     345                 :            : 
     346                 :          5 :         count = trace->nb_trace_mem_list;
     347                 :            : 
     348                 :            :         /* Allocate room for storing the thread trace mem meta */
     349                 :          5 :         trace->lcore_meta = realloc(trace->lcore_meta,
     350                 :          5 :                 sizeof(trace->lcore_meta[0]) * (count + 1));
     351                 :            : 
     352                 :            :         /* Provide dummy space for fast path to consume */
     353         [ -  + ]:          5 :         if (trace->lcore_meta == NULL) {
     354                 :          0 :                 trace_crit("trace mem meta memory realloc failed");
     355                 :            :                 header = NULL;
     356                 :          0 :                 goto fail;
     357                 :            :         }
     358                 :            : 
     359                 :            :         /* First attempt from huge page */
     360                 :          5 :         header = eal_malloc_no_trace(NULL, trace_mem_sz(trace->buff_len), 8);
     361         [ +  + ]:          5 :         if (header) {
     362                 :          3 :                 trace->lcore_meta[count].area = TRACE_AREA_HUGEPAGE;
     363                 :          3 :                 goto found;
     364                 :            :         }
     365                 :            : 
     366                 :            :         /* Second attempt from heap */
     367         [ -  + ]:          2 :         header = malloc(trace_mem_sz(trace->buff_len));
     368         [ -  + ]:          2 :         if (header == NULL) {
     369                 :          0 :                 trace_crit("trace mem malloc attempt failed");
     370                 :            :                 header = NULL;
     371                 :          0 :                 goto fail;
     372                 :            : 
     373                 :            :         }
     374                 :            : 
     375                 :            :         /* Second attempt from heap is success */
     376                 :          2 :         trace->lcore_meta[count].area = TRACE_AREA_HEAP;
     377                 :            : 
     378                 :            :         /* Initialize the trace header */
     379                 :          5 : found:
     380                 :          5 :         header->offset = 0;
     381                 :          5 :         header->len = trace->buff_len;
     382                 :          5 :         header->stream_header.magic = TRACE_CTF_MAGIC;
     383                 :          5 :         rte_uuid_copy(header->stream_header.uuid, trace->uuid);
     384                 :          5 :         header->stream_header.lcore_id = rte_lcore_id();
     385                 :            : 
     386                 :            :         /* Store the thread name */
     387                 :          5 :         char *name = header->stream_header.thread_name;
     388                 :            :         memset(name, 0, __RTE_TRACE_EMIT_STRING_LEN_MAX);
     389                 :          5 :         thread_get_name(rte_thread_self(), name,
     390                 :            :                 __RTE_TRACE_EMIT_STRING_LEN_MAX);
     391                 :            : 
     392                 :          5 :         trace->lcore_meta[count].mem = header;
     393                 :          5 :         trace->nb_trace_mem_list++;
     394                 :          5 : fail:
     395                 :          5 :         RTE_PER_LCORE(trace_mem) = header;
     396                 :            :         rte_spinlock_unlock(&trace->lock);
     397                 :            : }
     398                 :            : 
     399                 :            : static void
     400                 :          5 : trace_mem_per_thread_free_unlocked(struct thread_mem_meta *meta)
     401                 :            : {
     402         [ +  + ]:          5 :         if (meta->area == TRACE_AREA_HUGEPAGE)
     403                 :          3 :                 eal_free_no_trace(meta->mem);
     404         [ +  - ]:          2 :         else if (meta->area == TRACE_AREA_HEAP)
     405                 :          2 :                 free(meta->mem);
     406                 :          5 : }
     407                 :            : 
     408                 :            : void
     409                 :        129 : trace_mem_per_thread_free(void)
     410                 :            : {
     411                 :        129 :         struct trace *trace = trace_obj_get();
     412                 :            :         struct __rte_trace_header *header;
     413                 :            :         uint32_t count;
     414                 :            : 
     415                 :        129 :         header = RTE_PER_LCORE(trace_mem);
     416         [ -  + ]:        129 :         if (header == NULL)
     417                 :            :                 return;
     418                 :            : 
     419                 :          0 :         rte_spinlock_lock(&trace->lock);
     420         [ #  # ]:          0 :         for (count = 0; count < trace->nb_trace_mem_list; count++) {
     421         [ #  # ]:          0 :                 if (trace->lcore_meta[count].mem == header)
     422                 :            :                         break;
     423                 :            :         }
     424         [ #  # ]:          0 :         if (count != trace->nb_trace_mem_list) {
     425                 :          0 :                 struct thread_mem_meta *meta = &trace->lcore_meta[count];
     426                 :            : 
     427                 :          0 :                 trace_mem_per_thread_free_unlocked(meta);
     428         [ #  # ]:          0 :                 if (count != trace->nb_trace_mem_list - 1) {
     429                 :          0 :                         memmove(meta, meta + 1,
     430                 :            :                                 sizeof(*meta) *
     431                 :          0 :                                  (trace->nb_trace_mem_list - count - 1));
     432                 :            :                 }
     433                 :          0 :                 trace->nb_trace_mem_list--;
     434                 :            :         }
     435                 :            :         rte_spinlock_unlock(&trace->lock);
     436                 :            : }
     437                 :            : 
     438                 :            : void
     439                 :        252 : trace_mem_free(void)
     440                 :            : {
     441                 :        252 :         struct trace *trace = trace_obj_get();
     442                 :            :         uint32_t count;
     443                 :            : 
     444                 :        252 :         rte_spinlock_lock(&trace->lock);
     445         [ +  + ]:        257 :         for (count = 0; count < trace->nb_trace_mem_list; count++) {
     446                 :          5 :                 trace_mem_per_thread_free_unlocked(&trace->lcore_meta[count]);
     447                 :            :         }
     448                 :        252 :         trace->nb_trace_mem_list = 0;
     449                 :            :         rte_spinlock_unlock(&trace->lock);
     450                 :        252 : }
     451                 :            : 
     452                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(__rte_trace_point_emit_field, 20.05)
     453                 :            : void
     454                 :     500220 : __rte_trace_point_emit_field(size_t sz, const char *in, const char *datatype)
     455                 :            : {
     456                 :            :         char *field;
     457                 :            :         char *fixup;
     458                 :            :         int rc;
     459                 :            : 
     460                 :     500220 :         fixup = trace_metadata_fixup_field(in);
     461         [ +  + ]:     500220 :         if (fixup != NULL)
     462                 :            :                 in = fixup;
     463                 :     500220 :         rc = asprintf(&field, "%s        %s %s;\n",
     464         [ +  + ]:     500220 :                 RTE_PER_LCORE(ctf_field) != NULL ?
     465                 :            :                         RTE_PER_LCORE(ctf_field) : "",
     466                 :            :                 datatype, in);
     467                 :     500220 :         free(RTE_PER_LCORE(ctf_field));
     468                 :     500220 :         free(fixup);
     469         [ -  + ]:     500220 :         if (rc == -1) {
     470                 :          0 :                 RTE_PER_LCORE(trace_point_sz) = 0;
     471                 :          0 :                 RTE_PER_LCORE(ctf_field) = NULL;
     472                 :          0 :                 trace_crit("could not allocate CTF field");
     473                 :          0 :                 return;
     474                 :            :         }
     475                 :     500220 :         RTE_PER_LCORE(trace_point_sz) += sz;
     476                 :     500220 :         RTE_PER_LCORE(ctf_field) = field;
     477                 :            : }
     478                 :            : 
     479                 :            : RTE_EXPORT_EXPERIMENTAL_SYMBOL(__rte_trace_point_register, 20.05)
     480                 :            : int
     481                 :     134064 : __rte_trace_point_register(rte_trace_point_t *handle, const char *name,
     482                 :            :                 void (*register_fn)(void))
     483                 :            : {
     484                 :            :         struct trace_point *tp;
     485                 :            :         uint16_t sz;
     486                 :            : 
     487                 :            :         /* Sanity checks of arguments */
     488   [ +  -  -  + ]:     134064 :         if (name == NULL || register_fn == NULL || handle == NULL) {
     489                 :          0 :                 trace_err("invalid arguments");
     490                 :          0 :                 rte_errno = EINVAL;
     491                 :          0 :                 goto fail;
     492                 :            :         }
     493                 :            : 
     494                 :            :         /* Check the size of the trace point object */
     495                 :     134064 :         RTE_PER_LCORE(trace_point_sz) = 0;
     496                 :     134064 :         register_fn();
     497         [ -  + ]:     134064 :         if (RTE_PER_LCORE(trace_point_sz) == 0) {
     498                 :          0 :                 trace_err("missing rte_trace_emit_header() in register fn");
     499                 :          0 :                 rte_errno = EBADF;
     500                 :          0 :                 goto fail;
     501                 :            :         }
     502                 :            : 
     503                 :            :         /* Is size overflowed */
     504         [ -  + ]:     134064 :         if (RTE_PER_LCORE(trace_point_sz) > UINT16_MAX) {
     505                 :          0 :                 trace_err("trace point size overflowed");
     506                 :          0 :                 rte_errno = ENOSPC;
     507                 :          0 :                 goto fail;
     508                 :            :         }
     509                 :            : 
     510                 :            :         /* Are we running out of space to store trace points? */
     511         [ -  + ]:     134064 :         if (trace.nb_trace_points > UINT16_MAX) {
     512                 :          0 :                 trace_err("trace point exceeds the max count");
     513                 :          0 :                 rte_errno = ENOSPC;
     514                 :          0 :                 goto fail;
     515                 :            :         }
     516                 :            : 
     517                 :            :         /* Get the size of the trace point */
     518                 :     134064 :         sz = RTE_PER_LCORE(trace_point_sz);
     519                 :     134064 :         tp = calloc(1, sizeof(struct trace_point));
     520         [ -  + ]:     134064 :         if (tp == NULL) {
     521                 :          0 :                 trace_err("fail to allocate trace point memory");
     522                 :          0 :                 rte_errno = ENOMEM;
     523                 :          0 :                 goto fail;
     524                 :            :         }
     525                 :            : 
     526                 :            :         /* Initialize the trace point */
     527                 :     134064 :         tp->name = name;
     528                 :            : 
     529                 :            :         /* Copy the accumulated fields description and clear it for the next
     530                 :            :          * trace point.
     531                 :            :          */
     532                 :     134064 :         tp->ctf_field = RTE_PER_LCORE(ctf_field);
     533                 :     134064 :         RTE_PER_LCORE(ctf_field) = NULL;
     534                 :            : 
     535                 :            :         /* Form the trace handle */
     536                 :     134064 :         *handle = sz;
     537                 :     134064 :         *handle |= trace.nb_trace_points << __RTE_TRACE_FIELD_ID_SHIFT;
     538                 :     134064 :         trace_mode_set(handle, trace.mode);
     539                 :            : 
     540                 :     134064 :         trace.nb_trace_points++;
     541                 :     134064 :         tp->handle = handle;
     542                 :            : 
     543                 :            :         /* Add the trace point at tail */
     544                 :     134064 :         STAILQ_INSERT_TAIL(&tp_list, tp, next);
     545                 :            :         rte_atomic_thread_fence(rte_memory_order_release);
     546                 :            : 
     547                 :            :         /* All Good !!! */
     548                 :     134064 :         return 0;
     549                 :            : 
     550                 :          0 : fail:
     551         [ #  # ]:          0 :         if (trace.register_errno == 0)
     552                 :          0 :                 trace.register_errno = rte_errno;
     553                 :            : 
     554                 :          0 :         return -rte_errno;
     555                 :            : }

Generated by: LCOV version 1.14