LCOV - code coverage report
Current view: top level - lib/eal/common - rte_service.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 230 343 67.1 %
Date: 2024-04-01 19:00:53 Functions: 32 43 74.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 146 296 49.3 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2017 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <stdio.h>
       6                 :            : #include <inttypes.h>
       7                 :            : #include <string.h>
       8                 :            : 
       9                 :            : #include <rte_service.h>
      10                 :            : #include <rte_service_component.h>
      11                 :            : 
      12                 :            : #include <eal_trace_internal.h>
      13                 :            : #include <rte_lcore.h>
      14                 :            : #include <rte_branch_prediction.h>
      15                 :            : #include <rte_common.h>
      16                 :            : #include <rte_cycles.h>
      17                 :            : #include <rte_atomic.h>
      18                 :            : #include <rte_malloc.h>
      19                 :            : #include <rte_spinlock.h>
      20                 :            : #include <rte_trace_point.h>
      21                 :            : 
      22                 :            : #include "eal_private.h"
      23                 :            : 
      24                 :            : #define RTE_SERVICE_NUM_MAX 64
      25                 :            : 
      26                 :            : #define SERVICE_F_REGISTERED    (1 << 0)
      27                 :            : #define SERVICE_F_STATS_ENABLED (1 << 1)
      28                 :            : #define SERVICE_F_START_CHECK   (1 << 2)
      29                 :            : 
      30                 :            : /* runstates for services and lcores, denoting if they are active or not */
      31                 :            : #define RUNSTATE_STOPPED 0
      32                 :            : #define RUNSTATE_RUNNING 1
      33                 :            : 
      34                 :            : /* internal representation of a service */
      35                 :            : struct __rte_cache_aligned rte_service_spec_impl {
      36                 :            :         /* public part of the struct */
      37                 :            :         struct rte_service_spec spec;
      38                 :            : 
      39                 :            :         /* spin lock that when set indicates a service core is currently
      40                 :            :          * running this service callback. When not set, a core may take the
      41                 :            :          * lock and then run the service callback.
      42                 :            :          */
      43                 :            :         rte_spinlock_t execute_lock;
      44                 :            : 
      45                 :            :         /* API set/get-able variables */
      46                 :            :         RTE_ATOMIC(int8_t) app_runstate;
      47                 :            :         RTE_ATOMIC(int8_t) comp_runstate;
      48                 :            :         uint8_t internal_flags;
      49                 :            : 
      50                 :            :         /* per service statistics */
      51                 :            :         /* Indicates how many cores the service is mapped to run on.
      52                 :            :          * It does not indicate the number of cores the service is running
      53                 :            :          * on currently.
      54                 :            :          */
      55                 :            :         RTE_ATOMIC(uint32_t) num_mapped_cores;
      56                 :            : };
      57                 :            : 
      58                 :            : struct service_stats {
      59                 :            :         RTE_ATOMIC(uint64_t) calls;
      60                 :            :         RTE_ATOMIC(uint64_t) cycles;
      61                 :            : };
      62                 :            : 
      63                 :            : /* the internal values of a service core */
      64                 :            : struct __rte_cache_aligned core_state {
      65                 :            :         /* map of services IDs are run on this core */
      66                 :            :         uint64_t service_mask;
      67                 :            :         RTE_ATOMIC(uint8_t) runstate; /* running or stopped */
      68                 :            :         RTE_ATOMIC(uint8_t) thread_active; /* indicates when thread is in service_run() */
      69                 :            :         uint8_t is_service_core; /* set if core is currently a service core */
      70                 :            :         uint8_t service_active_on_lcore[RTE_SERVICE_NUM_MAX];
      71                 :            :         RTE_ATOMIC(uint64_t) loops;
      72                 :            :         RTE_ATOMIC(uint64_t) cycles;
      73                 :            :         struct service_stats service_stats[RTE_SERVICE_NUM_MAX];
      74                 :            : };
      75                 :            : 
      76                 :            : static uint32_t rte_service_count;
      77                 :            : static struct rte_service_spec_impl *rte_services;
      78                 :            : static struct core_state *lcore_states;
      79                 :            : static uint32_t rte_service_library_initialized;
      80                 :            : 
      81                 :            : int32_t
      82                 :        167 : rte_service_init(void)
      83                 :            : {
      84                 :            :         /* Hard limit due to the use of an uint64_t-based bitmask (and the
      85                 :            :          * clzl intrinsic).
      86                 :            :          */
      87                 :            :         RTE_BUILD_BUG_ON(RTE_SERVICE_NUM_MAX > 64);
      88                 :            : 
      89         [ -  + ]:        167 :         if (rte_service_library_initialized) {
      90                 :          0 :                 EAL_LOG(NOTICE,
      91                 :            :                         "service library init() called, init flag %d",
      92                 :            :                         rte_service_library_initialized);
      93                 :          0 :                 return -EALREADY;
      94                 :            :         }
      95                 :            : 
      96                 :        167 :         rte_services = rte_calloc("rte_services", RTE_SERVICE_NUM_MAX,
      97                 :            :                         sizeof(struct rte_service_spec_impl),
      98                 :            :                         RTE_CACHE_LINE_SIZE);
      99         [ -  + ]:        167 :         if (!rte_services) {
     100                 :          0 :                 EAL_LOG(ERR, "error allocating rte services array");
     101                 :          0 :                 goto fail_mem;
     102                 :            :         }
     103                 :            : 
     104                 :        167 :         lcore_states = rte_calloc("rte_service_core_states", RTE_MAX_LCORE,
     105                 :            :                         sizeof(struct core_state), RTE_CACHE_LINE_SIZE);
     106         [ -  + ]:        167 :         if (!lcore_states) {
     107                 :          0 :                 EAL_LOG(ERR, "error allocating core states array");
     108                 :          0 :                 goto fail_mem;
     109                 :            :         }
     110                 :            : 
     111                 :            :         int i;
     112                 :        167 :         struct rte_config *cfg = rte_eal_get_configuration();
     113         [ +  + ]:      21543 :         for (i = 0; i < RTE_MAX_LCORE; i++) {
     114         [ -  + ]:      21376 :                 if (lcore_config[i].core_role == ROLE_SERVICE) {
     115         [ #  # ]:          0 :                         if ((unsigned int)i == cfg->main_lcore)
     116                 :          0 :                                 continue;
     117                 :          0 :                         rte_service_lcore_add(i);
     118                 :            :                 }
     119                 :            :         }
     120                 :            : 
     121                 :        167 :         rte_service_library_initialized = 1;
     122                 :        167 :         return 0;
     123                 :          0 : fail_mem:
     124                 :          0 :         rte_free(rte_services);
     125                 :          0 :         rte_free(lcore_states);
     126                 :          0 :         return -ENOMEM;
     127                 :            : }
     128                 :            : 
     129                 :            : void
     130                 :        258 : rte_service_finalize(void)
     131                 :            : {
     132         [ +  + ]:        258 :         if (!rte_service_library_initialized)
     133                 :            :                 return;
     134                 :            : 
     135                 :        167 :         rte_service_lcore_reset_all();
     136                 :        167 :         rte_eal_mp_wait_lcore();
     137                 :            : 
     138                 :        167 :         rte_free(rte_services);
     139                 :        167 :         rte_free(lcore_states);
     140                 :            : 
     141                 :        167 :         rte_service_library_initialized = 0;
     142                 :            : }
     143                 :            : 
     144                 :            : static inline bool
     145                 :            : service_registered(uint32_t id)
     146                 :            : {
     147                 :    8402599 :         return rte_services[id].internal_flags & SERVICE_F_REGISTERED;
     148                 :            : }
     149                 :            : 
     150                 :            : static inline bool
     151                 :            : service_valid(uint32_t id)
     152                 :            : {
     153   [ +  -  -  +  :    8402419 :         return id < RTE_SERVICE_NUM_MAX && service_registered(id);
          -  -  -  -  -  
          +  +  -  -  +  
          +  +  -  +  -  
          +  -  +  -  +  
          -  +  -  +  -  
             +  -  +  -  
                      + ]
     154                 :            : }
     155                 :            : 
     156                 :            : static struct rte_service_spec_impl *
     157                 :            : service_get(uint32_t id)
     158                 :            : {
     159                 :     176366 :         return &rte_services[id];
     160                 :            : }
     161                 :            : 
     162                 :            : /* validate ID and retrieve service pointer, or return error value */
     163                 :            : #define SERVICE_VALID_GET_OR_ERR_RET(id, service, retval) do {          \
     164                 :            :         if (!service_valid(id))                                         \
     165                 :            :                 return retval;                                          \
     166                 :            :         service = &rte_services[id];                                    \
     167                 :            : } while (0)
     168                 :            : 
     169                 :            : /* returns 1 if statistics should be collected for service
     170                 :            :  * Returns 0 if statistics should not be collected for service
     171                 :            :  */
     172                 :            : static inline int
     173                 :            : service_stats_enabled(struct rte_service_spec_impl *impl)
     174                 :            : {
     175                 :    8402097 :         return !!(impl->internal_flags & SERVICE_F_STATS_ENABLED);
     176                 :            : }
     177                 :            : 
     178                 :            : static inline int
     179                 :            : service_mt_safe(struct rte_service_spec_impl *s)
     180                 :            : {
     181                 :    8402095 :         return !!(s->spec.capabilities & RTE_SERVICE_CAP_MT_SAFE);
     182                 :            : }
     183                 :            : 
     184                 :            : int32_t
     185         [ +  - ]:          2 : rte_service_set_stats_enable(uint32_t id, int32_t enabled)
     186                 :            : {
     187                 :            :         struct rte_service_spec_impl *s;
     188         [ +  - ]:          2 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, 0);
     189                 :            : 
     190         [ +  + ]:          2 :         if (enabled)
     191                 :          1 :                 s->internal_flags |= SERVICE_F_STATS_ENABLED;
     192                 :            :         else
     193                 :          1 :                 s->internal_flags &= ~(SERVICE_F_STATS_ENABLED);
     194                 :            : 
     195                 :            :         return 0;
     196                 :            : }
     197                 :            : 
     198                 :            : int32_t
     199         [ +  - ]:          3 : rte_service_set_runstate_mapped_check(uint32_t id, int32_t enabled)
     200                 :            : {
     201                 :            :         struct rte_service_spec_impl *s;
     202         [ +  - ]:          3 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, 0);
     203                 :            : 
     204         [ -  + ]:          3 :         if (enabled)
     205                 :          0 :                 s->internal_flags |= SERVICE_F_START_CHECK;
     206                 :            :         else
     207                 :          3 :                 s->internal_flags &= ~(SERVICE_F_START_CHECK);
     208                 :            : 
     209                 :            :         return 0;
     210                 :            : }
     211                 :            : 
     212                 :            : uint32_t
     213                 :        190 : rte_service_get_count(void)
     214                 :            : {
     215                 :        190 :         return rte_service_count;
     216                 :            : }
     217                 :            : 
     218                 :            : int32_t
     219                 :          4 : rte_service_get_by_name(const char *name, uint32_t *service_id)
     220                 :            : {
     221         [ +  + ]:          4 :         if (!service_id)
     222                 :            :                 return -EINVAL;
     223                 :            : 
     224                 :            :         int i;
     225         [ +  + ]:        131 :         for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
     226         [ +  + ]:        129 :                 if (service_registered(i) &&
     227         [ +  - ]:          1 :                                 strcmp(name, rte_services[i].spec.name) == 0) {
     228                 :          1 :                         *service_id = i;
     229                 :          1 :                         return 0;
     230                 :            :                 }
     231                 :            :         }
     232                 :            : 
     233                 :            :         return -ENODEV;
     234                 :            : }
     235                 :            : 
     236                 :            : const char *
     237         [ +  - ]:          1 : rte_service_get_name(uint32_t id)
     238                 :            : {
     239                 :            :         struct rte_service_spec_impl *s;
     240         [ +  - ]:          1 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, 0);
     241                 :          1 :         return s->spec.name;
     242                 :            : }
     243                 :            : 
     244                 :            : int32_t
     245         [ +  - ]:          2 : rte_service_probe_capability(uint32_t id, uint32_t capability)
     246                 :            : {
     247                 :            :         struct rte_service_spec_impl *s;
     248         [ +  - ]:          2 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
     249                 :          2 :         return !!(s->spec.capabilities & capability);
     250                 :            : }
     251                 :            : 
     252                 :            : int32_t
     253                 :         50 : rte_service_component_register(const struct rte_service_spec *spec,
     254                 :            :                                uint32_t *id_ptr)
     255                 :            : {
     256                 :            :         uint32_t i;
     257                 :            :         int32_t free_slot = -1;
     258                 :            : 
     259   [ +  +  +  + ]:         50 :         if (spec->callback == NULL || strlen(spec->name) == 0)
     260                 :            :                 return -EINVAL;
     261                 :            : 
     262         [ +  - ]:         52 :         for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
     263         [ +  + ]:         52 :                 if (!service_registered(i)) {
     264                 :         24 :                         free_slot = i;
     265                 :         24 :                         break;
     266                 :            :                 }
     267                 :            :         }
     268                 :            : 
     269         [ +  - ]:         24 :         if ((free_slot < 0) || (i == RTE_SERVICE_NUM_MAX))
     270                 :            :                 return -ENOSPC;
     271                 :            : 
     272                 :         24 :         struct rte_service_spec_impl *s = &rte_services[free_slot];
     273                 :         24 :         s->spec = *spec;
     274                 :         24 :         s->internal_flags |= SERVICE_F_REGISTERED | SERVICE_F_START_CHECK;
     275                 :            : 
     276                 :         24 :         rte_service_count++;
     277                 :            : 
     278         [ +  + ]:         24 :         if (id_ptr)
     279                 :         21 :                 *id_ptr = free_slot;
     280                 :            : 
     281         [ -  + ]:         24 :         rte_eal_trace_service_component_register(free_slot, spec->name);
     282                 :            : 
     283                 :         24 :         return 0;
     284                 :            : }
     285                 :            : 
     286                 :            : int32_t
     287         [ +  + ]:         37 : rte_service_component_unregister(uint32_t id)
     288                 :            : {
     289                 :            :         uint32_t i;
     290                 :            :         struct rte_service_spec_impl *s;
     291         [ +  + ]:         37 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
     292                 :            : 
     293                 :         14 :         rte_service_count--;
     294                 :            : 
     295                 :            :         s->internal_flags &= ~(SERVICE_F_REGISTERED);
     296                 :            : 
     297                 :            :         /* clear the run-bit in all cores */
     298         [ +  + ]:       1806 :         for (i = 0; i < RTE_MAX_LCORE; i++)
     299                 :       1792 :                 lcore_states[i].service_mask &= ~(UINT64_C(1) << id);
     300                 :            : 
     301                 :            :         memset(&rte_services[id], 0, sizeof(struct rte_service_spec_impl));
     302                 :            : 
     303                 :         14 :         return 0;
     304                 :            : }
     305                 :            : 
     306                 :            : int32_t
     307         [ +  - ]:         78 : rte_service_component_runstate_set(uint32_t id, uint32_t runstate)
     308                 :            : {
     309                 :            :         struct rte_service_spec_impl *s;
     310         [ +  - ]:         78 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
     311                 :            : 
     312                 :            :         /* comp_runstate act as the guard variable. Use store-release
     313                 :            :          * memory order. This synchronizes with load-acquire in
     314                 :            :          * service_run and service_runstate_get function.
     315                 :            :          */
     316         [ +  - ]:         78 :         if (runstate)
     317                 :         78 :                 rte_atomic_store_explicit(&s->comp_runstate, RUNSTATE_RUNNING,
     318                 :            :                         rte_memory_order_release);
     319                 :            :         else
     320                 :          0 :                 rte_atomic_store_explicit(&s->comp_runstate, RUNSTATE_STOPPED,
     321                 :            :                         rte_memory_order_release);
     322                 :            : 
     323                 :            :         return 0;
     324                 :            : }
     325                 :            : 
     326                 :            : int32_t
     327         [ +  - ]:        130 : rte_service_runstate_set(uint32_t id, uint32_t runstate)
     328                 :            : {
     329                 :            :         struct rte_service_spec_impl *s;
     330         [ +  - ]:        130 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
     331                 :            : 
     332                 :            :         /* app_runstate act as the guard variable. Use store-release
     333                 :            :          * memory order. This synchronizes with load-acquire in
     334                 :            :          * service_run runstate_get function.
     335                 :            :          */
     336         [ +  + ]:        130 :         if (runstate)
     337                 :         67 :                 rte_atomic_store_explicit(&s->app_runstate, RUNSTATE_RUNNING,
     338                 :            :                         rte_memory_order_release);
     339                 :            :         else
     340                 :         63 :                 rte_atomic_store_explicit(&s->app_runstate, RUNSTATE_STOPPED,
     341                 :            :                         rte_memory_order_release);
     342                 :            : 
     343                 :        130 :         rte_eal_trace_service_runstate_set(id, runstate);
     344                 :        130 :         return 0;
     345                 :            : }
     346                 :            : 
     347                 :            : int32_t
     348         [ +  - ]:        121 : rte_service_runstate_get(uint32_t id)
     349                 :            : {
     350                 :            :         struct rte_service_spec_impl *s;
     351         [ +  - ]:        121 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
     352                 :            : 
     353                 :            :         /* comp_runstate and app_runstate act as the guard variables.
     354                 :            :          * Use load-acquire memory order. This synchronizes with
     355                 :            :          * store-release in service state set functions.
     356                 :            :          */
     357         [ +  - ]:        121 :         if (rte_atomic_load_explicit(&s->comp_runstate, rte_memory_order_acquire) ==
     358                 :        121 :                         RUNSTATE_RUNNING &&
     359         [ +  + ]:        121 :             rte_atomic_load_explicit(&s->app_runstate, rte_memory_order_acquire) ==
     360                 :            :                         RUNSTATE_RUNNING) {
     361                 :        119 :                 int check_disabled = !(s->internal_flags &
     362                 :            :                         SERVICE_F_START_CHECK);
     363                 :        119 :                 int lcore_mapped = (rte_atomic_load_explicit(&s->num_mapped_cores,
     364                 :        119 :                         rte_memory_order_relaxed) > 0);
     365                 :            : 
     366                 :        119 :                 return (check_disabled | lcore_mapped);
     367                 :            :         } else
     368                 :          2 :                 return 0;
     369                 :            : 
     370                 :            : }
     371                 :            : 
     372                 :            : static inline void
     373         [ -  + ]:    8402095 : service_runner_do_callback(struct rte_service_spec_impl *s,
     374                 :            :                            struct core_state *cs, uint32_t service_idx)
     375                 :            : {
     376                 :    8402095 :         rte_eal_trace_service_run_begin(service_idx, rte_lcore_id());
     377                 :    8402095 :         void *userdata = s->spec.callback_userdata;
     378                 :            : 
     379         [ -  + ]:    8402095 :         if (service_stats_enabled(s)) {
     380                 :            :                 uint64_t start = rte_rdtsc();
     381                 :          0 :                 int rc = s->spec.callback(userdata);
     382                 :            : 
     383                 :            :                 /* The lcore service worker thread is the only writer,
     384                 :            :                  * and thus only a non-atomic load and an atomic store
     385                 :            :                  * is needed, and not the more expensive atomic
     386                 :            :                  * add.
     387                 :            :                  */
     388                 :            :                 struct service_stats *service_stats =
     389                 :            :                         &cs->service_stats[service_idx];
     390                 :            : 
     391         [ #  # ]:          0 :                 if (likely(rc != -EAGAIN)) {
     392                 :            :                         uint64_t end = rte_rdtsc();
     393                 :          0 :                         uint64_t cycles = end - start;
     394                 :            : 
     395                 :          0 :                         rte_atomic_store_explicit(&cs->cycles, cs->cycles + cycles,
     396                 :            :                                 rte_memory_order_relaxed);
     397                 :          0 :                         rte_atomic_store_explicit(&service_stats->cycles,
     398                 :            :                                 service_stats->cycles + cycles,
     399                 :            :                                 rte_memory_order_relaxed);
     400                 :            :                 }
     401                 :            : 
     402                 :          0 :                 rte_atomic_store_explicit(&service_stats->calls,
     403                 :            :                         service_stats->calls + 1, rte_memory_order_relaxed);
     404                 :            :         } else {
     405                 :    8402095 :                 s->spec.callback(userdata);
     406                 :            :         }
     407                 :    8402095 :         rte_eal_trace_service_run_end(service_idx, rte_lcore_id());
     408                 :    8402095 : }
     409                 :            : 
     410                 :            : 
     411                 :            : /* Expects the service 's' is valid. */
     412                 :            : static int32_t
     413                 :    8578359 : service_run(uint32_t i, struct core_state *cs, uint64_t service_mask,
     414                 :            :             struct rte_service_spec_impl *s, uint32_t serialize_mt_unsafe)
     415                 :            : {
     416         [ +  - ]:    8578359 :         if (!s)
     417                 :            :                 return -EINVAL;
     418                 :            : 
     419                 :            :         /* comp_runstate and app_runstate act as the guard variables.
     420                 :            :          * Use load-acquire memory order. This synchronizes with
     421                 :            :          * store-release in service state set functions.
     422                 :            :          */
     423         [ +  - ]:    8578359 :         if (rte_atomic_load_explicit(&s->comp_runstate, rte_memory_order_acquire) !=
     424                 :    8578359 :                         RUNSTATE_RUNNING ||
     425         [ +  + ]:    8578359 :             rte_atomic_load_explicit(&s->app_runstate, rte_memory_order_acquire) !=
     426                 :    8402095 :                         RUNSTATE_RUNNING ||
     427         [ -  + ]:    8402095 :             !(service_mask & (UINT64_C(1) << i))) {
     428                 :     176264 :                 cs->service_active_on_lcore[i] = 0;
     429                 :     176264 :                 return -ENOEXEC;
     430                 :            :         }
     431                 :            : 
     432                 :    8402095 :         cs->service_active_on_lcore[i] = 1;
     433                 :            : 
     434   [ +  +  +  + ]:    8402095 :         if ((service_mt_safe(s) == 0) && (serialize_mt_unsafe == 1)) {
     435         [ +  - ]:       5295 :                 if (!rte_spinlock_trylock(&s->execute_lock))
     436                 :            :                         return -EBUSY;
     437                 :            : 
     438                 :       5295 :                 service_runner_do_callback(s, cs, i);
     439                 :            :                 rte_spinlock_unlock(&s->execute_lock);
     440                 :            :         } else
     441                 :    8396800 :                 service_runner_do_callback(s, cs, i);
     442                 :            : 
     443                 :            :         return 0;
     444                 :            : }
     445                 :            : 
     446                 :            : int32_t
     447                 :         63 : rte_service_may_be_active(uint32_t id)
     448                 :            : {
     449                 :         63 :         uint32_t ids[RTE_MAX_LCORE] = {0};
     450                 :         63 :         int32_t lcore_count = rte_service_lcore_list(ids, RTE_MAX_LCORE);
     451                 :            :         int i;
     452                 :            : 
     453         [ +  + ]:         63 :         if (!service_valid(id))
     454                 :            :                 return -EINVAL;
     455                 :            : 
     456         [ +  + ]:         64 :         for (i = 0; i < lcore_count; i++) {
     457         [ +  + ]:          3 :                 if (lcore_states[ids[i]].service_active_on_lcore[id])
     458                 :            :                         return 1;
     459                 :            :         }
     460                 :            : 
     461                 :            :         return 0;
     462                 :            : }
     463                 :            : 
     464                 :            : int32_t
     465                 :    8401995 : rte_service_run_iter_on_app_lcore(uint32_t id, uint32_t serialize_mt_unsafe)
     466                 :            : {
     467         [ +  - ]:    8401995 :         struct core_state *cs = &lcore_states[rte_lcore_id()];
     468                 :            :         struct rte_service_spec_impl *s;
     469                 :            : 
     470         [ +  - ]:    8401995 :         SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
     471                 :            : 
     472                 :            :         /* Increment num_mapped_cores to reflect that this core is
     473                 :            :          * now mapped capable of running the service.
     474                 :            :          */
     475                 :    8401995 :         rte_atomic_fetch_add_explicit(&s->num_mapped_cores, 1, rte_memory_order_relaxed);
     476                 :            : 
     477                 :    8401995 :         int ret = service_run(id, cs, UINT64_MAX, s, serialize_mt_unsafe);
     478                 :            : 
     479                 :    8401995 :         rte_atomic_fetch_sub_explicit(&s->num_mapped_cores, 1, rte_memory_order_relaxed);
     480                 :            : 
     481                 :    8401995 :         return ret;
     482                 :            : }
     483                 :            : 
     484                 :            : static int32_t
     485                 :          1 : service_runner_func(void *arg)
     486                 :            : {
     487                 :            :         RTE_SET_USED(arg);
     488                 :            :         uint8_t i;
     489                 :          1 :         const int lcore = rte_lcore_id();
     490                 :          1 :         struct core_state *cs = &lcore_states[lcore];
     491                 :            : 
     492                 :          1 :         rte_atomic_store_explicit(&cs->thread_active, 1, rte_memory_order_seq_cst);
     493                 :            : 
     494                 :            :         /* runstate act as the guard variable. Use load-acquire
     495                 :            :          * memory order here to synchronize with store-release
     496                 :            :          * in runstate update functions.
     497                 :            :          */
     498         [ +  + ]:     176533 :         while (rte_atomic_load_explicit(&cs->runstate, rte_memory_order_acquire) ==
     499                 :            :                         RUNSTATE_RUNNING) {
     500                 :            : 
     501                 :     176532 :                 const uint64_t service_mask = cs->service_mask;
     502                 :            :                 uint8_t start_id;
     503                 :            :                 uint8_t end_id;
     504                 :            : 
     505         [ +  + ]:     176532 :                 if (service_mask == 0)
     506                 :        168 :                         continue;
     507                 :            : 
     508                 :     176364 :                 start_id = rte_ctz64(service_mask);
     509                 :     176364 :                 end_id = 64 - rte_clz64(service_mask);
     510                 :            : 
     511         [ +  + ]:     352728 :                 for (i = start_id; i < end_id; i++) {
     512                 :            :                         /* return value ignored as no change to code flow */
     513                 :     176364 :                         service_run(i, cs, service_mask, service_get(i), 1);
     514                 :            :                 }
     515                 :            : 
     516                 :     176364 :                 rte_atomic_store_explicit(&cs->loops, cs->loops + 1, rte_memory_order_relaxed);
     517                 :            :         }
     518                 :            : 
     519                 :            :         /* Switch off this core for all services, to ensure that future
     520                 :            :          * calls to may_be_active() know this core is switched off.
     521                 :            :          */
     522         [ +  + ]:         65 :         for (i = 0; i < RTE_SERVICE_NUM_MAX; i++)
     523                 :         64 :                 cs->service_active_on_lcore[i] = 0;
     524                 :            : 
     525                 :            :         /* Use SEQ CST memory ordering to avoid any re-ordering around
     526                 :            :          * this store, ensuring that once this store is visible, the service
     527                 :            :          * lcore thread really is done in service cores code.
     528                 :            :          */
     529                 :          1 :         rte_atomic_store_explicit(&cs->thread_active, 0, rte_memory_order_seq_cst);
     530                 :          1 :         return 0;
     531                 :            : }
     532                 :            : 
     533                 :            : int32_t
     534                 :          0 : rte_service_lcore_may_be_active(uint32_t lcore)
     535                 :            : {
     536   [ #  #  #  # ]:          0 :         if (lcore >= RTE_MAX_LCORE || !lcore_states[lcore].is_service_core)
     537                 :            :                 return -EINVAL;
     538                 :            : 
     539                 :            :         /* Load thread_active using ACQUIRE to avoid instructions dependent on
     540                 :            :          * the result being re-ordered before this load completes.
     541                 :            :          */
     542                 :          0 :         return rte_atomic_load_explicit(&lcore_states[lcore].thread_active,
     543                 :            :                                rte_memory_order_acquire);
     544                 :            : }
     545                 :            : 
     546                 :            : int32_t
     547                 :        230 : rte_service_lcore_count(void)
     548                 :            : {
     549                 :            :         int32_t count = 0;
     550                 :            :         uint32_t i;
     551         [ +  + ]:      29670 :         for (i = 0; i < RTE_MAX_LCORE; i++)
     552                 :      29440 :                 count += lcore_states[i].is_service_core;
     553                 :        230 :         return count;
     554                 :            : }
     555                 :            : 
     556                 :            : int32_t
     557                 :        230 : rte_service_lcore_list(uint32_t array[], uint32_t n)
     558                 :            : {
     559                 :        230 :         uint32_t count = rte_service_lcore_count();
     560         [ +  - ]:        230 :         if (count > n)
     561                 :            :                 return -ENOMEM;
     562                 :            : 
     563         [ +  - ]:        230 :         if (!array)
     564                 :            :                 return -EINVAL;
     565                 :            : 
     566                 :            :         uint32_t i;
     567                 :            :         uint32_t idx = 0;
     568         [ +  + ]:      29670 :         for (i = 0; i < RTE_MAX_LCORE; i++) {
     569                 :      29440 :                 struct core_state *cs = &lcore_states[i];
     570         [ +  + ]:      29440 :                 if (cs->is_service_core) {
     571                 :          3 :                         array[idx] = i;
     572                 :          3 :                         idx++;
     573                 :            :                 }
     574                 :            :         }
     575                 :            : 
     576                 :            :         return count;
     577                 :            : }
     578                 :            : 
     579                 :            : int32_t
     580                 :          0 : rte_service_lcore_count_services(uint32_t lcore)
     581                 :            : {
     582         [ #  # ]:          0 :         if (lcore >= RTE_MAX_LCORE)
     583                 :            :                 return -EINVAL;
     584                 :            : 
     585                 :          0 :         struct core_state *cs = &lcore_states[lcore];
     586         [ #  # ]:          0 :         if (!cs->is_service_core)
     587                 :            :                 return -ENOTSUP;
     588                 :            : 
     589                 :          0 :         return rte_popcount64(cs->service_mask);
     590                 :            : }
     591                 :            : 
     592                 :            : int32_t
     593                 :        167 : rte_service_start_with_defaults(void)
     594                 :            : {
     595                 :            :         /* create a default mapping from cores to services, then start the
     596                 :            :          * services to make them transparent to unaware applications.
     597                 :            :          */
     598                 :            :         uint32_t i;
     599                 :            :         int ret;
     600                 :        167 :         uint32_t count = rte_service_get_count();
     601                 :            : 
     602                 :            :         int32_t lcore_iter = 0;
     603                 :        167 :         uint32_t ids[RTE_MAX_LCORE] = {0};
     604                 :        167 :         int32_t lcore_count = rte_service_lcore_list(ids, RTE_MAX_LCORE);
     605                 :            : 
     606         [ -  + ]:        167 :         if (lcore_count == 0)
     607                 :            :                 return -ENOTSUP;
     608                 :            : 
     609         [ #  # ]:          0 :         for (i = 0; (int)i < lcore_count; i++)
     610                 :          0 :                 rte_service_lcore_start(ids[i]);
     611                 :            : 
     612         [ #  # ]:          0 :         for (i = 0; i < count; i++) {
     613                 :            :                 /* do 1:1 core mapping here, with each service getting
     614                 :            :                  * assigned a single core by default. Adding multiple services
     615                 :            :                  * should multiplex to a single core, or 1:1 if there are the
     616                 :            :                  * same amount of services as service-cores
     617                 :            :                  */
     618                 :          0 :                 ret = rte_service_map_lcore_set(i, ids[lcore_iter], 1);
     619         [ #  # ]:          0 :                 if (ret)
     620                 :            :                         return -ENODEV;
     621                 :            : 
     622                 :          0 :                 lcore_iter++;
     623         [ #  # ]:          0 :                 if (lcore_iter >= lcore_count)
     624                 :            :                         lcore_iter = 0;
     625                 :            : 
     626                 :          0 :                 ret = rte_service_runstate_set(i, 1);
     627         [ #  # ]:          0 :                 if (ret)
     628                 :            :                         return -ENOEXEC;
     629                 :            :         }
     630                 :            : 
     631                 :            :         return 0;
     632                 :            : }
     633                 :            : 
     634                 :            : static int32_t
     635         [ +  - ]:          8 : service_update(uint32_t sid, uint32_t lcore, uint32_t *set, uint32_t *enabled)
     636                 :            : {
     637                 :            :         /* validate ID, or return error value */
     638   [ +  -  +  + ]:          8 :         if (!service_valid(sid) || lcore >= RTE_MAX_LCORE ||
     639         [ +  - ]:          6 :                         !lcore_states[lcore].is_service_core)
     640                 :            :                 return -EINVAL;
     641                 :            : 
     642                 :          6 :         uint64_t sid_mask = UINT64_C(1) << sid;
     643         [ +  + ]:          6 :         if (set) {
     644                 :          4 :                 uint64_t lcore_mapped = lcore_states[lcore].service_mask &
     645                 :            :                         sid_mask;
     646                 :            : 
     647   [ +  +  +  - ]:          4 :                 if (*set && !lcore_mapped) {
     648                 :          3 :                         lcore_states[lcore].service_mask |= sid_mask;
     649                 :          3 :                         rte_atomic_fetch_add_explicit(&rte_services[sid].num_mapped_cores,
     650                 :            :                                 1, rte_memory_order_relaxed);
     651                 :            :                 }
     652   [ +  +  +  - ]:          4 :                 if (!*set && lcore_mapped) {
     653                 :          1 :                         lcore_states[lcore].service_mask &= ~(sid_mask);
     654                 :          1 :                         rte_atomic_fetch_sub_explicit(&rte_services[sid].num_mapped_cores,
     655                 :            :                                 1, rte_memory_order_relaxed);
     656                 :            :                 }
     657                 :            :         }
     658                 :            : 
     659         [ +  + ]:          6 :         if (enabled)
     660                 :          2 :                 *enabled = !!(lcore_states[lcore].service_mask & (sid_mask));
     661                 :            : 
     662                 :            :         return 0;
     663                 :            : }
     664                 :            : 
     665                 :            : int32_t
     666                 :          6 : rte_service_map_lcore_set(uint32_t id, uint32_t lcore, uint32_t enabled)
     667                 :            : {
     668         [ -  + ]:          6 :         uint32_t on = enabled > 0;
     669                 :          6 :         rte_eal_trace_service_map_lcore(id, lcore, enabled);
     670                 :          6 :         return service_update(id, lcore, &on, 0);
     671                 :            : }
     672                 :            : 
     673                 :            : int32_t
     674                 :          2 : rte_service_map_lcore_get(uint32_t id, uint32_t lcore)
     675                 :            : {
     676                 :            :         uint32_t enabled;
     677                 :          2 :         int ret = service_update(id, lcore, 0, &enabled);
     678         [ +  - ]:          2 :         if (ret == 0)
     679                 :          2 :                 return enabled;
     680                 :            :         return ret;
     681                 :            : }
     682                 :            : 
     683                 :            : static void
     684                 :          6 : set_lcore_state(uint32_t lcore, int32_t state)
     685                 :            : {
     686                 :            :         /* mark core state in hugepage backed config */
     687                 :          6 :         struct rte_config *cfg = rte_eal_get_configuration();
     688                 :          6 :         cfg->lcore_role[lcore] = state;
     689                 :            : 
     690                 :            :         /* mark state in process local lcore_config */
     691                 :          6 :         lcore_config[lcore].core_role = state;
     692                 :            : 
     693                 :            :         /* update per-lcore optimized state tracking */
     694         [ -  + ]:          6 :         lcore_states[lcore].is_service_core = (state == ROLE_SERVICE);
     695                 :            : 
     696                 :          6 :         rte_eal_trace_service_lcore_state_change(lcore, state);
     697                 :          6 : }
     698                 :            : 
     699                 :            : int32_t
     700                 :        190 : rte_service_lcore_reset_all(void)
     701                 :            : {
     702                 :            :         /* loop over cores, reset all to mask 0 */
     703                 :            :         uint32_t i;
     704         [ +  + ]:      24510 :         for (i = 0; i < RTE_MAX_LCORE; i++) {
     705         [ +  + ]:      24320 :                 if (lcore_states[i].is_service_core) {
     706                 :          3 :                         lcore_states[i].service_mask = 0;
     707                 :          3 :                         set_lcore_state(i, ROLE_RTE);
     708                 :            :                         /* runstate act as guard variable Use
     709                 :            :                          * store-release memory order here to synchronize
     710                 :            :                          * with load-acquire in runstate read functions.
     711                 :            :                          */
     712                 :          3 :                         rte_atomic_store_explicit(&lcore_states[i].runstate,
     713                 :            :                                 RUNSTATE_STOPPED, rte_memory_order_release);
     714                 :            :                 }
     715                 :            :         }
     716         [ +  + ]:      12350 :         for (i = 0; i < RTE_SERVICE_NUM_MAX; i++)
     717                 :      12160 :                 rte_atomic_store_explicit(&rte_services[i].num_mapped_cores, 0,
     718                 :            :                         rte_memory_order_relaxed);
     719                 :            : 
     720                 :        190 :         return 0;
     721                 :            : }
     722                 :            : 
     723                 :            : int32_t
     724                 :          3 : rte_service_lcore_add(uint32_t lcore)
     725                 :            : {
     726         [ +  - ]:          3 :         if (lcore >= RTE_MAX_LCORE)
     727                 :            :                 return -EINVAL;
     728         [ +  - ]:          3 :         if (lcore_states[lcore].is_service_core)
     729                 :            :                 return -EALREADY;
     730                 :            : 
     731                 :          3 :         set_lcore_state(lcore, ROLE_SERVICE);
     732                 :            : 
     733                 :            :         /* ensure that after adding a core the mask and state are defaults */
     734                 :          3 :         lcore_states[lcore].service_mask = 0;
     735                 :            :         /* Use store-release memory order here to synchronize with
     736                 :            :          * load-acquire in runstate read functions.
     737                 :            :          */
     738                 :          3 :         rte_atomic_store_explicit(&lcore_states[lcore].runstate, RUNSTATE_STOPPED,
     739                 :            :                 rte_memory_order_release);
     740                 :            : 
     741                 :          3 :         return rte_eal_wait_lcore(lcore);
     742                 :            : }
     743                 :            : 
     744                 :            : int32_t
     745                 :          0 : rte_service_lcore_del(uint32_t lcore)
     746                 :            : {
     747         [ #  # ]:          0 :         if (lcore >= RTE_MAX_LCORE)
     748                 :            :                 return -EINVAL;
     749                 :            : 
     750                 :          0 :         struct core_state *cs = &lcore_states[lcore];
     751         [ #  # ]:          0 :         if (!cs->is_service_core)
     752                 :            :                 return -EINVAL;
     753                 :            : 
     754                 :            :         /* runstate act as the guard variable. Use load-acquire
     755                 :            :          * memory order here to synchronize with store-release
     756                 :            :          * in runstate update functions.
     757                 :            :          */
     758         [ #  # ]:          0 :         if (rte_atomic_load_explicit(&cs->runstate, rte_memory_order_acquire) !=
     759                 :            :                         RUNSTATE_STOPPED)
     760                 :            :                 return -EBUSY;
     761                 :            : 
     762                 :          0 :         set_lcore_state(lcore, ROLE_RTE);
     763                 :            : 
     764                 :          0 :         rte_smp_wmb();
     765                 :          0 :         return 0;
     766                 :            : }
     767                 :            : 
     768                 :            : int32_t
     769                 :          1 : rte_service_lcore_start(uint32_t lcore)
     770                 :            : {
     771         [ +  - ]:          1 :         if (lcore >= RTE_MAX_LCORE)
     772                 :            :                 return -EINVAL;
     773                 :            : 
     774                 :          1 :         struct core_state *cs = &lcore_states[lcore];
     775         [ +  - ]:          1 :         if (!cs->is_service_core)
     776                 :            :                 return -EINVAL;
     777                 :            : 
     778                 :            :         /* runstate act as the guard variable. Use load-acquire
     779                 :            :          * memory order here to synchronize with store-release
     780                 :            :          * in runstate update functions.
     781                 :            :          */
     782         [ +  - ]:          1 :         if (rte_atomic_load_explicit(&cs->runstate, rte_memory_order_acquire) ==
     783                 :            :                         RUNSTATE_RUNNING)
     784                 :            :                 return -EALREADY;
     785                 :            : 
     786                 :            :         /* set core to run state first, and then launch otherwise it will
     787                 :            :          * return immediately as runstate keeps it in the service poll loop
     788                 :            :          */
     789                 :            :         /* Use load-acquire memory order here to synchronize with
     790                 :            :          * store-release in runstate update functions.
     791                 :            :          */
     792         [ -  + ]:          1 :         rte_atomic_store_explicit(&cs->runstate, RUNSTATE_RUNNING, rte_memory_order_release);
     793                 :            : 
     794                 :          1 :         rte_eal_trace_service_lcore_start(lcore);
     795                 :            : 
     796                 :          1 :         int ret = rte_eal_remote_launch(service_runner_func, 0, lcore);
     797                 :            :         /* returns -EBUSY if the core is already launched, 0 on success */
     798                 :          1 :         return ret;
     799                 :            : }
     800                 :            : 
     801                 :            : int32_t
     802                 :          0 : rte_service_lcore_stop(uint32_t lcore)
     803                 :            : {
     804         [ #  # ]:          0 :         if (lcore >= RTE_MAX_LCORE)
     805                 :            :                 return -EINVAL;
     806                 :            : 
     807                 :            :         /* runstate act as the guard variable. Use load-acquire
     808                 :            :          * memory order here to synchronize with store-release
     809                 :            :          * in runstate update functions.
     810                 :            :          */
     811         [ #  # ]:          0 :         if (rte_atomic_load_explicit(&lcore_states[lcore].runstate, rte_memory_order_acquire) ==
     812                 :            :                         RUNSTATE_STOPPED)
     813                 :            :                 return -EALREADY;
     814                 :            : 
     815                 :            :         uint32_t i;
     816                 :          0 :         struct core_state *cs = &lcore_states[lcore];
     817                 :          0 :         uint64_t service_mask = cs->service_mask;
     818                 :            : 
     819         [ #  # ]:          0 :         for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
     820                 :          0 :                 int32_t enabled = service_mask & (UINT64_C(1) << i);
     821                 :          0 :                 int32_t service_running = rte_service_runstate_get(i);
     822                 :            :                 int32_t only_core = (1 ==
     823                 :          0 :                         rte_atomic_load_explicit(&rte_services[i].num_mapped_cores,
     824                 :            :                                 rte_memory_order_relaxed));
     825                 :            : 
     826                 :            :                 /* if the core is mapped, and the service is running, and this
     827                 :            :                  * is the only core that is mapped, the service would cease to
     828                 :            :                  * run if this core stopped, so fail instead.
     829                 :            :                  */
     830   [ #  #  #  # ]:          0 :                 if (enabled && service_running && only_core)
     831                 :            :                         return -EBUSY;
     832                 :            :         }
     833                 :            : 
     834                 :            :         /* Use store-release memory order here to synchronize with
     835                 :            :          * load-acquire in runstate read functions.
     836                 :            :          */
     837         [ #  # ]:          0 :         rte_atomic_store_explicit(&lcore_states[lcore].runstate, RUNSTATE_STOPPED,
     838                 :            :                 rte_memory_order_release);
     839                 :            : 
     840                 :          0 :         rte_eal_trace_service_lcore_stop(lcore);
     841                 :            : 
     842                 :          0 :         return 0;
     843                 :            : }
     844                 :            : 
     845                 :            : static uint64_t
     846                 :            : lcore_attr_get_loops(unsigned int lcore)
     847                 :            : {
     848                 :            :         struct core_state *cs = &lcore_states[lcore];
     849                 :            : 
     850                 :          0 :         return rte_atomic_load_explicit(&cs->loops, rte_memory_order_relaxed);
     851                 :            : }
     852                 :            : 
     853                 :            : static uint64_t
     854                 :            : lcore_attr_get_cycles(unsigned int lcore)
     855                 :            : {
     856                 :            :         struct core_state *cs = &lcore_states[lcore];
     857                 :            : 
     858                 :          0 :         return rte_atomic_load_explicit(&cs->cycles, rte_memory_order_relaxed);
     859                 :            : }
     860                 :            : 
     861                 :            : static uint64_t
     862                 :          0 : lcore_attr_get_service_calls(uint32_t service_id, unsigned int lcore)
     863                 :            : {
     864                 :          0 :         struct core_state *cs = &lcore_states[lcore];
     865                 :            : 
     866                 :          0 :         return rte_atomic_load_explicit(&cs->service_stats[service_id].calls,
     867                 :            :                 rte_memory_order_relaxed);
     868                 :            : }
     869                 :            : 
     870                 :            : static uint64_t
     871                 :          0 : lcore_attr_get_service_cycles(uint32_t service_id, unsigned int lcore)
     872                 :            : {
     873                 :          0 :         struct core_state *cs = &lcore_states[lcore];
     874                 :            : 
     875                 :          0 :         return rte_atomic_load_explicit(&cs->service_stats[service_id].cycles,
     876                 :            :                 rte_memory_order_relaxed);
     877                 :            : }
     878                 :            : 
     879                 :            : typedef uint64_t (*lcore_attr_get_fun)(uint32_t service_id,
     880                 :            :                                        unsigned int lcore);
     881                 :            : 
     882                 :            : static uint64_t
     883                 :            : attr_get(uint32_t id, lcore_attr_get_fun lcore_attr_get)
     884                 :            : {
     885                 :            :         unsigned int lcore;
     886                 :            :         uint64_t sum = 0;
     887                 :            : 
     888   [ +  +  +  + ]:        516 :         for (lcore = 0; lcore < RTE_MAX_LCORE; lcore++) {
     889   [ -  +  -  + ]:        512 :                 if (lcore_states[lcore].is_service_core)
     890                 :          0 :                         sum += lcore_attr_get(id, lcore);
     891                 :            :         }
     892                 :            : 
     893                 :            :         return sum;
     894                 :            : }
     895                 :            : 
     896                 :            : static uint64_t
     897                 :          2 : attr_get_service_calls(uint32_t service_id)
     898                 :            : {
     899                 :          2 :         return attr_get(service_id, lcore_attr_get_service_calls);
     900                 :            : }
     901                 :            : 
     902                 :            : static uint64_t
     903                 :          2 : attr_get_service_cycles(uint32_t service_id)
     904                 :            : {
     905                 :          2 :         return attr_get(service_id, lcore_attr_get_service_cycles);
     906                 :            : }
     907                 :            : 
     908                 :            : int32_t
     909         [ #  # ]:          0 : rte_service_attr_get(uint32_t id, uint32_t attr_id, uint64_t *attr_value)
     910                 :            : {
     911         [ #  # ]:          0 :         if (!service_valid(id))
     912                 :            :                 return -EINVAL;
     913                 :            : 
     914         [ #  # ]:          0 :         if (!attr_value)
     915                 :            :                 return -EINVAL;
     916                 :            : 
     917      [ #  #  # ]:          0 :         switch (attr_id) {
     918                 :          0 :         case RTE_SERVICE_ATTR_CALL_COUNT:
     919                 :          0 :                 *attr_value = attr_get_service_calls(id);
     920                 :          0 :                 return 0;
     921                 :          0 :         case RTE_SERVICE_ATTR_CYCLES:
     922                 :          0 :                 *attr_value = attr_get_service_cycles(id);
     923                 :          0 :                 return 0;
     924                 :            :         default:
     925                 :            :                 return -EINVAL;
     926                 :            :         }
     927                 :            : }
     928                 :            : 
     929                 :            : int32_t
     930                 :          0 : rte_service_lcore_attr_get(uint32_t lcore, uint32_t attr_id,
     931                 :            :                            uint64_t *attr_value)
     932                 :            : {
     933                 :            :         struct core_state *cs;
     934                 :            : 
     935         [ #  # ]:          0 :         if (lcore >= RTE_MAX_LCORE || !attr_value)
     936                 :            :                 return -EINVAL;
     937                 :            : 
     938                 :          0 :         cs = &lcore_states[lcore];
     939         [ #  # ]:          0 :         if (!cs->is_service_core)
     940                 :            :                 return -ENOTSUP;
     941                 :            : 
     942      [ #  #  # ]:          0 :         switch (attr_id) {
     943                 :            :         case RTE_SERVICE_LCORE_ATTR_LOOPS:
     944                 :          0 :                 *attr_value = lcore_attr_get_loops(lcore);
     945                 :          0 :                 return 0;
     946                 :            :         case RTE_SERVICE_LCORE_ATTR_CYCLES:
     947                 :          0 :                 *attr_value = lcore_attr_get_cycles(lcore);
     948                 :          0 :                 return 0;
     949                 :            :         default:
     950                 :            :                 return -EINVAL;
     951                 :            :         }
     952                 :            : }
     953                 :            : 
     954                 :            : int32_t
     955         [ #  # ]:          0 : rte_service_attr_reset_all(uint32_t id)
     956                 :            : {
     957                 :            :         unsigned int lcore;
     958                 :            : 
     959         [ #  # ]:          0 :         if (!service_valid(id))
     960                 :            :                 return -EINVAL;
     961                 :            : 
     962         [ #  # ]:          0 :         for (lcore = 0; lcore < RTE_MAX_LCORE; lcore++) {
     963                 :          0 :                 struct core_state *cs = &lcore_states[lcore];
     964                 :            : 
     965                 :          0 :                 cs->service_stats[id] = (struct service_stats) {};
     966                 :            :         }
     967                 :            : 
     968                 :            :         return 0;
     969                 :            : }
     970                 :            : 
     971                 :            : int32_t
     972                 :          0 : rte_service_lcore_attr_reset_all(uint32_t lcore)
     973                 :            : {
     974                 :            :         struct core_state *cs;
     975                 :            : 
     976         [ #  # ]:          0 :         if (lcore >= RTE_MAX_LCORE)
     977                 :            :                 return -EINVAL;
     978                 :            : 
     979                 :          0 :         cs = &lcore_states[lcore];
     980         [ #  # ]:          0 :         if (!cs->is_service_core)
     981                 :            :                 return -ENOTSUP;
     982                 :            : 
     983                 :          0 :         cs->loops = 0;
     984                 :            : 
     985                 :          0 :         return 0;
     986                 :            : }
     987                 :            : 
     988                 :            : static void
     989                 :          2 : service_dump_one(FILE *f, uint32_t id)
     990                 :            : {
     991                 :            :         struct rte_service_spec_impl *s;
     992                 :            :         uint64_t service_calls;
     993                 :            :         uint64_t service_cycles;
     994                 :            : 
     995                 :          2 :         service_calls = attr_get_service_calls(id);
     996                 :          2 :         service_cycles = attr_get_service_cycles(id);
     997                 :            : 
     998                 :            :         /* avoid divide by zero */
     999                 :            :         if (service_calls == 0)
    1000                 :            :                 service_calls = 1;
    1001                 :            : 
    1002                 :            :         s = service_get(id);
    1003                 :            : 
    1004                 :          2 :         fprintf(f, "  %s: stats %d\tcalls %"PRIu64"\tcycles %"
    1005                 :            :                 PRIu64"\tavg: %"PRIu64"\n",
    1006                 :          2 :                 s->spec.name, service_stats_enabled(s), service_calls,
    1007                 :            :                 service_cycles, service_cycles / service_calls);
    1008                 :          2 : }
    1009                 :            : 
    1010                 :            : static void
    1011                 :          0 : service_dump_calls_per_lcore(FILE *f, uint32_t lcore)
    1012                 :            : {
    1013                 :            :         uint32_t i;
    1014                 :          0 :         struct core_state *cs = &lcore_states[lcore];
    1015                 :            : 
    1016                 :            :         fprintf(f, "%02d\t", lcore);
    1017         [ #  # ]:          0 :         for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
    1018         [ #  # ]:          0 :                 if (!service_registered(i))
    1019                 :          0 :                         continue;
    1020                 :          0 :                 fprintf(f, "%"PRIu64"\t", cs->service_stats[i].calls);
    1021                 :            :         }
    1022                 :            :         fprintf(f, "\n");
    1023                 :          0 : }
    1024                 :            : 
    1025                 :            : int32_t
    1026                 :          2 : rte_service_dump(FILE *f, uint32_t id)
    1027                 :            : {
    1028                 :            :         uint32_t i;
    1029                 :            :         int print_one = (id != UINT32_MAX);
    1030                 :            : 
    1031                 :            :         /* print only the specified service */
    1032         [ +  - ]:          2 :         if (print_one) {
    1033                 :            :                 struct rte_service_spec_impl *s;
    1034         [ +  - ]:          2 :                 SERVICE_VALID_GET_OR_ERR_RET(id, s, -EINVAL);
    1035                 :          2 :                 fprintf(f, "Service %s Summary\n", s->spec.name);
    1036                 :          2 :                 service_dump_one(f, id);
    1037                 :          2 :                 return 0;
    1038                 :            :         }
    1039                 :            : 
    1040                 :            :         /* print all services, as UINT32_MAX was passed as id */
    1041                 :            :         fprintf(f, "Services Summary\n");
    1042         [ #  # ]:          0 :         for (i = 0; i < RTE_SERVICE_NUM_MAX; i++) {
    1043         [ #  # ]:          0 :                 if (!service_registered(i))
    1044                 :          0 :                         continue;
    1045                 :          0 :                 service_dump_one(f, i);
    1046                 :            :         }
    1047                 :            : 
    1048                 :            :         fprintf(f, "Service Cores Summary\n");
    1049         [ #  # ]:          0 :         for (i = 0; i < RTE_MAX_LCORE; i++) {
    1050         [ #  # ]:          0 :                 if (lcore_config[i].core_role != ROLE_SERVICE)
    1051                 :          0 :                         continue;
    1052                 :            : 
    1053                 :          0 :                 service_dump_calls_per_lcore(f, i);
    1054                 :            :         }
    1055                 :            : 
    1056                 :            :         return 0;
    1057                 :            : }

Generated by: LCOV version 1.14