LCOV - code coverage report
Current view: top level - lib/eal/common - rte_service.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 225 358 62.8 %
Date: 2025-01-02 22:41:34 Functions: 32 48 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 162 352 46.0 %

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

Generated by: LCOV version 1.14