LCOV - code coverage report
Current view: top level - lib/eal/common - eal_common_lcore.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 186 292 63.7 %
Date: 2024-02-14 00:53:57 Functions: 21 32 65.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 83 164 50.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  * Copyright(c) 2010-2014 Intel Corporation
       3                 :            :  */
       4                 :            : 
       5                 :            : #include <inttypes.h>
       6                 :            : #include <stdlib.h>
       7                 :            : #include <string.h>
       8                 :            : 
       9                 :            : #include <rte_common.h>
      10                 :            : #include <rte_branch_prediction.h>
      11                 :            : #include <rte_errno.h>
      12                 :            : #include <rte_lcore.h>
      13                 :            : #include <rte_log.h>
      14                 :            : #ifndef RTE_EXEC_ENV_WINDOWS
      15                 :            : #include <rte_telemetry.h>
      16                 :            : #endif
      17                 :            : 
      18                 :            : #include "eal_private.h"
      19                 :            : #include "eal_thread.h"
      20                 :            : 
      21                 :       2173 : unsigned int rte_get_main_lcore(void)
      22                 :            : {
      23                 :       2173 :         return rte_eal_get_configuration()->main_lcore;
      24                 :            : }
      25                 :            : 
      26                 :      12767 : unsigned int rte_lcore_count(void)
      27                 :            : {
      28                 :      12767 :         return rte_eal_get_configuration()->lcore_count;
      29                 :            : }
      30                 :            : 
      31                 :          0 : int rte_lcore_index(int lcore_id)
      32                 :            : {
      33         [ #  # ]:          0 :         if (unlikely(lcore_id >= RTE_MAX_LCORE))
      34                 :            :                 return -1;
      35                 :            : 
      36         [ #  # ]:          0 :         if (lcore_id < 0) {
      37         [ #  # ]:          0 :                 if (rte_lcore_id() == LCORE_ID_ANY)
      38                 :            :                         return -1;
      39                 :            : 
      40                 :          0 :                 lcore_id = (int)rte_lcore_id();
      41                 :            :         }
      42                 :            : 
      43                 :          0 :         return lcore_config[lcore_id].core_index;
      44                 :            : }
      45                 :            : 
      46                 :          0 : int rte_lcore_to_cpu_id(int lcore_id)
      47                 :            : {
      48         [ #  # ]:          0 :         if (unlikely(lcore_id >= RTE_MAX_LCORE))
      49                 :            :                 return -1;
      50                 :            : 
      51         [ #  # ]:          0 :         if (lcore_id < 0) {
      52         [ #  # ]:          0 :                 if (rte_lcore_id() == LCORE_ID_ANY)
      53                 :            :                         return -1;
      54                 :            : 
      55                 :          0 :                 lcore_id = (int)rte_lcore_id();
      56                 :            :         }
      57                 :            : 
      58                 :          0 :         return lcore_config[lcore_id].core_id;
      59                 :            : }
      60                 :            : 
      61                 :          0 : rte_cpuset_t rte_lcore_cpuset(unsigned int lcore_id)
      62                 :            : {
      63                 :          0 :         return lcore_config[lcore_id].cpuset;
      64                 :            : }
      65                 :            : 
      66                 :            : enum rte_lcore_role_t
      67                 :          1 : rte_eal_lcore_role(unsigned int lcore_id)
      68                 :            : {
      69                 :          1 :         struct rte_config *cfg = rte_eal_get_configuration();
      70                 :            : 
      71         [ +  - ]:          1 :         if (lcore_id >= RTE_MAX_LCORE)
      72                 :            :                 return ROLE_OFF;
      73                 :          1 :         return cfg->lcore_role[lcore_id];
      74                 :            : }
      75                 :            : 
      76                 :            : int
      77                 :      24448 : rte_lcore_has_role(unsigned int lcore_id, enum rte_lcore_role_t role)
      78                 :            : {
      79                 :      24448 :         struct rte_config *cfg = rte_eal_get_configuration();
      80                 :            : 
      81         [ +  - ]:      24448 :         if (lcore_id >= RTE_MAX_LCORE)
      82                 :            :                 return -EINVAL;
      83                 :            : 
      84                 :      24448 :         return cfg->lcore_role[lcore_id] == role;
      85                 :            : }
      86                 :            : 
      87                 :   53799015 : int rte_lcore_is_enabled(unsigned int lcore_id)
      88                 :            : {
      89                 :   53799015 :         struct rte_config *cfg = rte_eal_get_configuration();
      90                 :            : 
      91         [ +  - ]:   53778190 :         if (lcore_id >= RTE_MAX_LCORE)
      92                 :            :                 return 0;
      93                 :   53778190 :         return cfg->lcore_role[lcore_id] == ROLE_RTE;
      94                 :            : }
      95                 :            : 
      96                 :     843049 : unsigned int rte_get_next_lcore(unsigned int i, int skip_main, int wrap)
      97                 :            : {
      98                 :     843049 :         i++;
      99         [ +  + ]:     843049 :         if (wrap)
     100                 :     840936 :                 i %= RTE_MAX_LCORE;
     101                 :            : 
     102         [ +  + ]:   53862921 :         while (i < RTE_MAX_LCORE) {
     103   [ +  +  +  + ]:   53861862 :                 if (!rte_lcore_is_enabled(i) ||
     104         [ +  + ]:       1751 :                     (skip_main && (i == rte_get_main_lcore()))) {
     105                 :   53019872 :                         i++;
     106         [ +  + ]:   53019872 :                         if (wrap)
     107                 :   52885353 :                                 i %= RTE_MAX_LCORE;
     108                 :   53019872 :                         continue;
     109                 :            :                 }
     110                 :            :                 break;
     111                 :            :         }
     112                 :     851162 :         return i;
     113                 :            : }
     114                 :            : 
     115                 :            : unsigned int
     116                 :        265 : rte_lcore_to_socket_id(unsigned int lcore_id)
     117                 :            : {
     118                 :        265 :         return lcore_config[lcore_id].socket_id;
     119                 :            : }
     120                 :            : 
     121                 :            : static int
     122                 :     125960 : socket_id_cmp(const void *a, const void *b)
     123                 :            : {
     124                 :            :         const int *lcore_id_a = a;
     125                 :            :         const int *lcore_id_b = b;
     126                 :            : 
     127         [ +  + ]:     125960 :         if (*lcore_id_a < *lcore_id_b)
     128                 :            :                 return -1;
     129         [ +  + ]:     124080 :         if (*lcore_id_a > *lcore_id_b)
     130                 :      26320 :                 return 1;
     131                 :            :         return 0;
     132                 :            : }
     133                 :            : 
     134                 :            : /*
     135                 :            :  * Parse /sys/devices/system/cpu to get the number of physical and logical
     136                 :            :  * processors on the machine. The function will fill the cpu_info
     137                 :            :  * structure.
     138                 :            :  */
     139                 :            : int
     140                 :        235 : rte_eal_cpu_init(void)
     141                 :            : {
     142                 :            :         /* pointer to global configuration */
     143                 :        235 :         struct rte_config *config = rte_eal_get_configuration();
     144                 :            :         unsigned lcore_id;
     145                 :            :         unsigned count = 0;
     146                 :            :         unsigned int socket_id, prev_socket_id;
     147                 :            :         int lcore_to_socket_id[RTE_MAX_LCORE];
     148                 :            : 
     149                 :            :         /*
     150                 :            :          * Parse the maximum set of logical cores, detect the subset of running
     151                 :            :          * ones and enable them by default.
     152                 :            :          */
     153         [ +  + ]:      30315 :         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
     154                 :      30080 :                 lcore_config[lcore_id].core_index = count;
     155                 :            : 
     156                 :            :                 /* init cpuset for per lcore config */
     157                 :      30080 :                 CPU_ZERO(&lcore_config[lcore_id].cpuset);
     158                 :            : 
     159                 :            :                 /* find socket first */
     160                 :      30080 :                 socket_id = eal_cpu_socket_id(lcore_id);
     161                 :      30080 :                 lcore_to_socket_id[lcore_id] = socket_id;
     162                 :            : 
     163         [ +  + ]:      30080 :                 if (eal_cpu_detected(lcore_id) == 0) {
     164                 :      26320 :                         config->lcore_role[lcore_id] = ROLE_OFF;
     165                 :      26320 :                         lcore_config[lcore_id].core_index = -1;
     166                 :      26320 :                         continue;
     167                 :            :                 }
     168                 :            : 
     169                 :            :                 /* By default, lcore 1:1 map to cpu id */
     170                 :       3760 :                 CPU_SET(lcore_id, &lcore_config[lcore_id].cpuset);
     171                 :            : 
     172                 :            :                 /* By default, each detected core is enabled */
     173                 :       3760 :                 config->lcore_role[lcore_id] = ROLE_RTE;
     174                 :       3760 :                 lcore_config[lcore_id].core_role = ROLE_RTE;
     175                 :       3760 :                 lcore_config[lcore_id].core_id = eal_cpu_core_id(lcore_id);
     176                 :       3760 :                 lcore_config[lcore_id].socket_id = socket_id;
     177                 :       3760 :                 EAL_LOG(DEBUG, "Detected lcore %u as "
     178                 :            :                                 "core %u on socket %u",
     179                 :            :                                 lcore_id, lcore_config[lcore_id].core_id,
     180                 :            :                                 lcore_config[lcore_id].socket_id);
     181                 :       3760 :                 count++;
     182                 :            :         }
     183         [ +  + ]:     210795 :         for (; lcore_id < CPU_SETSIZE; lcore_id++) {
     184         [ +  - ]:     210560 :                 if (eal_cpu_detected(lcore_id) == 0)
     185                 :     210560 :                         continue;
     186                 :          0 :                 EAL_LOG(DEBUG, "Skipped lcore %u as core %u on socket %u",
     187                 :            :                         lcore_id, eal_cpu_core_id(lcore_id),
     188                 :            :                         eal_cpu_socket_id(lcore_id));
     189                 :            :         }
     190                 :            : 
     191                 :            :         /* Set the count of enabled logical cores of the EAL configuration */
     192                 :        235 :         config->lcore_count = count;
     193                 :        235 :         EAL_LOG(DEBUG,
     194                 :            :                         "Maximum logical cores by configuration: %u",
     195                 :            :                         RTE_MAX_LCORE);
     196                 :        235 :         EAL_LOG(INFO, "Detected CPU lcores: %u", config->lcore_count);
     197                 :            : 
     198                 :            :         /* sort all socket id's in ascending order */
     199                 :        235 :         qsort(lcore_to_socket_id, RTE_DIM(lcore_to_socket_id),
     200                 :            :                         sizeof(lcore_to_socket_id[0]), socket_id_cmp);
     201                 :            : 
     202                 :            :         prev_socket_id = -1;
     203                 :        235 :         config->numa_node_count = 0;
     204         [ +  + ]:      30315 :         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
     205                 :      30080 :                 socket_id = lcore_to_socket_id[lcore_id];
     206         [ +  + ]:      30080 :                 if (socket_id != prev_socket_id)
     207                 :        470 :                         config->numa_nodes[config->numa_node_count++] =
     208                 :            :                                         socket_id;
     209                 :            :                 prev_socket_id = socket_id;
     210                 :            :         }
     211                 :        235 :         EAL_LOG(INFO, "Detected NUMA nodes: %u", config->numa_node_count);
     212                 :            : 
     213                 :        235 :         return 0;
     214                 :            : }
     215                 :            : 
     216                 :            : unsigned int
     217                 :       1019 : rte_socket_count(void)
     218                 :            : {
     219                 :       1019 :         const struct rte_config *config = rte_eal_get_configuration();
     220                 :       1019 :         return config->numa_node_count;
     221                 :            : }
     222                 :            : 
     223                 :            : int
     224                 :      83381 : rte_socket_id_by_idx(unsigned int idx)
     225                 :            : {
     226                 :      83381 :         const struct rte_config *config = rte_eal_get_configuration();
     227         [ +  + ]:      83381 :         if (idx >= config->numa_node_count) {
     228                 :         10 :                 rte_errno = EINVAL;
     229                 :         10 :                 return -1;
     230                 :            :         }
     231                 :      83371 :         return config->numa_nodes[idx];
     232                 :            : }
     233                 :            : 
     234                 :            : static rte_rwlock_t lcore_lock = RTE_RWLOCK_INITIALIZER;
     235                 :            : struct lcore_callback {
     236                 :            :         TAILQ_ENTRY(lcore_callback) next;
     237                 :            :         char *name;
     238                 :            :         rte_lcore_init_cb init;
     239                 :            :         rte_lcore_uninit_cb uninit;
     240                 :            :         void *arg;
     241                 :            : };
     242                 :            : static TAILQ_HEAD(lcore_callbacks_head, lcore_callback) lcore_callbacks =
     243                 :            :         TAILQ_HEAD_INITIALIZER(lcore_callbacks);
     244                 :            : 
     245                 :            : static int
     246                 :         12 : callback_init(struct lcore_callback *callback, unsigned int lcore_id)
     247                 :            : {
     248         [ +  - ]:         12 :         if (callback->init == NULL)
     249                 :            :                 return 0;
     250                 :         12 :         EAL_LOG(DEBUG, "Call init for lcore callback %s, lcore_id %u",
     251                 :            :                 callback->name, lcore_id);
     252                 :         12 :         return callback->init(lcore_id, callback->arg);
     253                 :            : }
     254                 :            : 
     255                 :            : static void
     256                 :         10 : callback_uninit(struct lcore_callback *callback, unsigned int lcore_id)
     257                 :            : {
     258         [ +  - ]:         10 :         if (callback->uninit == NULL)
     259                 :            :                 return;
     260                 :         10 :         EAL_LOG(DEBUG, "Call uninit for lcore callback %s, lcore_id %u",
     261                 :            :                 callback->name, lcore_id);
     262                 :         10 :         callback->uninit(lcore_id, callback->arg);
     263                 :            : }
     264                 :            : 
     265                 :            : static void
     266                 :            : free_callback(struct lcore_callback *callback)
     267                 :            : {
     268                 :          4 :         free(callback->name);
     269                 :          4 :         free(callback);
     270                 :          3 : }
     271                 :            : 
     272                 :            : void *
     273                 :          4 : rte_lcore_callback_register(const char *name, rte_lcore_init_cb init,
     274                 :            :         rte_lcore_uninit_cb uninit, void *arg)
     275                 :            : {
     276                 :          4 :         struct rte_config *cfg = rte_eal_get_configuration();
     277                 :            :         struct lcore_callback *callback;
     278                 :            :         unsigned int lcore_id;
     279                 :            : 
     280         [ +  - ]:          4 :         if (name == NULL)
     281                 :            :                 return NULL;
     282                 :          4 :         callback = calloc(1, sizeof(*callback));
     283         [ +  - ]:          4 :         if (callback == NULL)
     284                 :            :                 return NULL;
     285         [ -  + ]:          4 :         if (asprintf(&callback->name, "%s-%p", name, arg) == -1) {
     286                 :          0 :                 free(callback);
     287                 :          0 :                 return NULL;
     288                 :            :         }
     289                 :          4 :         callback->init = init;
     290                 :          4 :         callback->uninit = uninit;
     291                 :          4 :         callback->arg = arg;
     292                 :          4 :         rte_rwlock_write_lock(&lcore_lock);
     293         [ -  + ]:          4 :         if (callback->init == NULL)
     294                 :          0 :                 goto no_init;
     295         [ +  + ]:        389 :         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
     296         [ +  + ]:        386 :                 if (cfg->lcore_role[lcore_id] == ROLE_OFF)
     297                 :        378 :                         continue;
     298         [ +  + ]:          8 :                 if (callback_init(callback, lcore_id) == 0)
     299                 :          7 :                         continue;
     300                 :            :                 /* Callback refused init for this lcore, uninitialize all
     301                 :            :                  * previous lcore.
     302                 :            :                  */
     303         [ +  + ]:          2 :                 while (lcore_id-- != 0) {
     304         [ -  + ]:          1 :                         if (cfg->lcore_role[lcore_id] == ROLE_OFF)
     305                 :          0 :                                 continue;
     306                 :          1 :                         callback_uninit(callback, lcore_id);
     307                 :            :                 }
     308                 :            :                 free_callback(callback);
     309                 :            :                 callback = NULL;
     310                 :          1 :                 goto out;
     311                 :            :         }
     312                 :          3 : no_init:
     313                 :          3 :         TAILQ_INSERT_TAIL(&lcore_callbacks, callback, next);
     314   [ +  -  +  - ]:          9 :         EAL_LOG(DEBUG, "Registered new lcore callback %s (%sinit, %suninit).",
     315                 :            :                 callback->name, callback->init == NULL ? "NO " : "",
     316                 :            :                 callback->uninit == NULL ? "NO " : "");
     317                 :          4 : out:
     318                 :            :         rte_rwlock_write_unlock(&lcore_lock);
     319                 :          4 :         return callback;
     320                 :            : }
     321                 :            : 
     322                 :            : void
     323                 :          3 : rte_lcore_callback_unregister(void *handle)
     324                 :            : {
     325                 :          3 :         struct rte_config *cfg = rte_eal_get_configuration();
     326                 :            :         struct lcore_callback *callback = handle;
     327                 :            :         unsigned int lcore_id;
     328                 :            : 
     329         [ +  - ]:          3 :         if (callback == NULL)
     330                 :            :                 return;
     331                 :          3 :         rte_rwlock_write_lock(&lcore_lock);
     332         [ -  + ]:          3 :         if (callback->uninit == NULL)
     333                 :          0 :                 goto no_uninit;
     334         [ +  + ]:        387 :         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
     335         [ +  + ]:        384 :                 if (cfg->lcore_role[lcore_id] == ROLE_OFF)
     336                 :        378 :                         continue;
     337                 :          6 :                 callback_uninit(callback, lcore_id);
     338                 :            :         }
     339                 :          3 : no_uninit:
     340         [ +  + ]:          3 :         TAILQ_REMOVE(&lcore_callbacks, callback, next);
     341                 :            :         rte_rwlock_write_unlock(&lcore_lock);
     342                 :          3 :         EAL_LOG(DEBUG, "Unregistered lcore callback %s-%p.",
     343                 :            :                 callback->name, callback->arg);
     344                 :            :         free_callback(callback);
     345                 :            : }
     346                 :            : 
     347                 :            : unsigned int
     348                 :        129 : eal_lcore_non_eal_allocate(void)
     349                 :            : {
     350                 :        129 :         struct rte_config *cfg = rte_eal_get_configuration();
     351                 :            :         struct lcore_callback *callback;
     352                 :            :         struct lcore_callback *prev;
     353                 :            :         unsigned int lcore_id;
     354                 :            : 
     355                 :        129 :         rte_rwlock_write_lock(&lcore_lock);
     356         [ +  + ]:       8389 :         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
     357         [ +  + ]:       8388 :                 if (cfg->lcore_role[lcore_id] != ROLE_OFF)
     358                 :            :                         continue;
     359                 :        128 :                 cfg->lcore_role[lcore_id] = ROLE_NON_EAL;
     360                 :        128 :                 cfg->lcore_count++;
     361                 :        128 :                 break;
     362                 :            :         }
     363         [ +  + ]:        129 :         if (lcore_id == RTE_MAX_LCORE) {
     364                 :          1 :                 EAL_LOG(DEBUG, "No lcore available.");
     365                 :          1 :                 goto out;
     366                 :            :         }
     367         [ +  + ]:        131 :         TAILQ_FOREACH(callback, &lcore_callbacks, next) {
     368         [ +  + ]:          4 :                 if (callback_init(callback, lcore_id) == 0)
     369                 :            :                         continue;
     370                 :            :                 /* Callback refused init for this lcore, call uninit for all
     371                 :            :                  * previous callbacks.
     372                 :            :                  */
     373                 :          1 :                 prev = TAILQ_PREV(callback, lcore_callbacks_head, next);
     374         [ +  + ]:          2 :                 while (prev != NULL) {
     375                 :          1 :                         callback_uninit(prev, lcore_id);
     376                 :          1 :                         prev = TAILQ_PREV(prev, lcore_callbacks_head, next);
     377                 :            :                 }
     378                 :          1 :                 EAL_LOG(DEBUG, "Initialization refused for lcore %u.",
     379                 :            :                         lcore_id);
     380                 :          1 :                 cfg->lcore_role[lcore_id] = ROLE_OFF;
     381                 :          1 :                 cfg->lcore_count--;
     382                 :            :                 lcore_id = RTE_MAX_LCORE;
     383                 :          1 :                 goto out;
     384                 :            :         }
     385                 :        127 : out:
     386                 :            :         rte_rwlock_write_unlock(&lcore_lock);
     387                 :        129 :         return lcore_id;
     388                 :            : }
     389                 :            : 
     390                 :            : void
     391                 :        127 : eal_lcore_non_eal_release(unsigned int lcore_id)
     392                 :            : {
     393                 :        127 :         struct rte_config *cfg = rte_eal_get_configuration();
     394                 :            :         struct lcore_callback *callback;
     395                 :            : 
     396                 :        127 :         rte_rwlock_write_lock(&lcore_lock);
     397         [ -  + ]:        127 :         if (cfg->lcore_role[lcore_id] != ROLE_NON_EAL)
     398                 :          0 :                 goto out;
     399         [ +  + ]:        129 :         TAILQ_FOREACH(callback, &lcore_callbacks, next)
     400                 :          2 :                 callback_uninit(callback, lcore_id);
     401                 :        127 :         cfg->lcore_role[lcore_id] = ROLE_OFF;
     402                 :        127 :         cfg->lcore_count--;
     403                 :        127 : out:
     404                 :            :         rte_rwlock_write_unlock(&lcore_lock);
     405                 :        127 : }
     406                 :            : 
     407                 :            : int
     408                 :          3 : rte_lcore_iterate(rte_lcore_iterate_cb cb, void *arg)
     409                 :            : {
     410                 :          3 :         struct rte_config *cfg = rte_eal_get_configuration();
     411                 :            :         unsigned int lcore_id;
     412                 :            :         int ret = 0;
     413                 :            : 
     414                 :          3 :         rte_rwlock_read_lock(&lcore_lock);
     415         [ +  + ]:        387 :         for (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {
     416         [ +  + ]:        384 :                 if (cfg->lcore_role[lcore_id] == ROLE_OFF)
     417                 :        377 :                         continue;
     418                 :          7 :                 ret = cb(lcore_id, arg);
     419         [ +  - ]:          7 :                 if (ret != 0)
     420                 :            :                         break;
     421                 :            :         }
     422                 :            :         rte_rwlock_read_unlock(&lcore_lock);
     423                 :          3 :         return ret;
     424                 :            : }
     425                 :            : 
     426                 :            : static const char *
     427                 :            : lcore_role_str(enum rte_lcore_role_t role)
     428                 :            : {
     429                 :          7 :         switch (role) {
     430                 :            :         case ROLE_RTE:
     431                 :            :                 return "RTE";
     432                 :          0 :         case ROLE_SERVICE:
     433                 :          0 :                 return "SERVICE";
     434                 :          1 :         case ROLE_NON_EAL:
     435                 :          1 :                 return "NON_EAL";
     436                 :          0 :         default:
     437                 :          0 :                 return "UNKNOWN";
     438                 :            :         }
     439                 :            : }
     440                 :            : 
     441                 :            : static rte_lcore_usage_cb lcore_usage_cb;
     442                 :            : 
     443                 :            : void
     444                 :          0 : rte_lcore_register_usage_cb(rte_lcore_usage_cb cb)
     445                 :            : {
     446                 :          0 :         lcore_usage_cb = cb;
     447                 :          0 : }
     448                 :            : 
     449                 :            : static float
     450                 :            : calc_usage_ratio(const struct rte_lcore_usage *usage)
     451                 :            : {
     452                 :          0 :         return usage->total_cycles != 0 ?
     453         [ #  # ]:          0 :                 (usage->busy_cycles * 100.0) / usage->total_cycles : (float)0;
     454                 :            : }
     455                 :            : 
     456                 :            : static int
     457                 :          7 : lcore_dump_cb(unsigned int lcore_id, void *arg)
     458                 :            : {
     459                 :          7 :         struct rte_config *cfg = rte_eal_get_configuration();
     460                 :            :         char cpuset[RTE_CPU_AFFINITY_STR_LEN];
     461                 :            :         struct rte_lcore_usage usage;
     462                 :            :         rte_lcore_usage_cb usage_cb;
     463         [ -  + ]:          7 :         char *usage_str = NULL;
     464                 :            :         FILE *f = arg;
     465                 :            :         int ret;
     466                 :            : 
     467                 :            :         /* The callback may not set all the fields in the structure, so clear it here. */
     468                 :            :         memset(&usage, 0, sizeof(usage));
     469                 :            :         /* Guard against concurrent modification of lcore_usage_cb. */
     470                 :          7 :         usage_cb = lcore_usage_cb;
     471   [ -  +  -  - ]:          7 :         if (usage_cb != NULL && usage_cb(lcore_id, &usage) == 0) {
     472         [ #  # ]:          0 :                 if (asprintf(&usage_str, ", busy cycles %"PRIu64"/%"PRIu64" (ratio %.02f%%)",
     473                 :            :                                 usage.busy_cycles, usage.total_cycles,
     474                 :            :                                 calc_usage_ratio(&usage)) < 0) {
     475                 :            :                         return -ENOMEM;
     476                 :            :                 }
     477                 :            :         }
     478                 :          7 :         ret = eal_thread_dump_affinity(&lcore_config[lcore_id].cpuset, cpuset,
     479                 :            :                 sizeof(cpuset));
     480   [ -  +  -  +  :          8 :         fprintf(f, "lcore %u, socket %u, role %s, cpuset %s%s%s\n", lcore_id,
                   -  + ]
     481                 :            :                 rte_lcore_to_socket_id(lcore_id),
     482                 :            :                 lcore_role_str(cfg->lcore_role[lcore_id]), cpuset,
     483         [ -  + ]:          7 :                 ret == 0 ? "" : "...", usage_str != NULL ? usage_str : "");
     484                 :          7 :         free(usage_str);
     485                 :            : 
     486                 :          7 :         return 0;
     487                 :            : }
     488                 :            : 
     489                 :            : void
     490                 :          3 : rte_lcore_dump(FILE *f)
     491                 :            : {
     492                 :          3 :         rte_lcore_iterate(lcore_dump_cb, f);
     493                 :          3 : }
     494                 :            : 
     495                 :            : #ifndef RTE_EXEC_ENV_WINDOWS
     496                 :            : static int
     497                 :          0 : lcore_telemetry_id_cb(unsigned int lcore_id, void *arg)
     498                 :            : {
     499                 :            :         struct rte_tel_data *d = arg;
     500                 :            : 
     501                 :          0 :         return rte_tel_data_add_array_int(d, lcore_id);
     502                 :            : }
     503                 :            : 
     504                 :            : static int
     505                 :          0 : handle_lcore_list(const char *cmd __rte_unused, const char *params __rte_unused,
     506                 :            :         struct rte_tel_data *d)
     507                 :            : {
     508                 :            :         int ret;
     509                 :            : 
     510                 :          0 :         ret = rte_tel_data_start_array(d, RTE_TEL_INT_VAL);
     511         [ #  # ]:          0 :         if (ret == 0)
     512                 :          0 :                 ret = rte_lcore_iterate(lcore_telemetry_id_cb, d);
     513                 :            : 
     514                 :          0 :         return ret;
     515                 :            : }
     516                 :            : 
     517                 :            : struct lcore_telemetry_info {
     518                 :            :         unsigned int lcore_id;
     519                 :            :         struct rte_tel_data *d;
     520                 :            : };
     521                 :            : 
     522                 :            : static void
     523         [ #  # ]:          0 : format_usage_ratio(char *buf, uint16_t size, const struct rte_lcore_usage *usage)
     524                 :            : {
     525                 :            :         float ratio = calc_usage_ratio(usage);
     526                 :          0 :         snprintf(buf, size, "%.02f%%", ratio);
     527                 :          0 : }
     528                 :            : 
     529                 :            : static int
     530                 :          0 : lcore_telemetry_info_cb(unsigned int lcore_id, void *arg)
     531                 :            : {
     532                 :          0 :         struct rte_config *cfg = rte_eal_get_configuration();
     533                 :            :         struct lcore_telemetry_info *info = arg;
     534                 :            :         char ratio_str[RTE_TEL_MAX_STRING_LEN];
     535                 :            :         struct rte_lcore_usage usage;
     536                 :            :         struct rte_tel_data *cpuset;
     537                 :            :         rte_lcore_usage_cb usage_cb;
     538                 :            :         unsigned int cpu;
     539                 :            : 
     540         [ #  # ]:          0 :         if (lcore_id != info->lcore_id)
     541                 :            :                 return 0;
     542                 :            : 
     543                 :          0 :         rte_tel_data_start_dict(info->d);
     544                 :          0 :         rte_tel_data_add_dict_int(info->d, "lcore_id", lcore_id);
     545                 :          0 :         rte_tel_data_add_dict_int(info->d, "socket", rte_lcore_to_socket_id(lcore_id));
     546   [ #  #  #  # ]:          0 :         rte_tel_data_add_dict_string(info->d, "role", lcore_role_str(cfg->lcore_role[lcore_id]));
     547                 :          0 :         cpuset = rte_tel_data_alloc();
     548         [ #  # ]:          0 :         if (cpuset == NULL)
     549                 :            :                 return -ENOMEM;
     550                 :          0 :         rte_tel_data_start_array(cpuset, RTE_TEL_INT_VAL);
     551         [ #  # ]:          0 :         for (cpu = 0; cpu < CPU_SETSIZE; cpu++) {
     552         [ #  # ]:          0 :                 if (CPU_ISSET(cpu, &lcore_config[lcore_id].cpuset))
     553                 :          0 :                         rte_tel_data_add_array_int(cpuset, cpu);
     554                 :            :         }
     555                 :          0 :         rte_tel_data_add_dict_container(info->d, "cpuset", cpuset, 0);
     556                 :            :         /* The callback may not set all the fields in the structure, so clear it here. */
     557                 :            :         memset(&usage, 0, sizeof(usage));
     558                 :            :         /* Guard against concurrent modification of lcore_usage_cb. */
     559                 :          0 :         usage_cb = lcore_usage_cb;
     560   [ #  #  #  # ]:          0 :         if (usage_cb != NULL && usage_cb(lcore_id, &usage) == 0) {
     561                 :          0 :                 rte_tel_data_add_dict_uint(info->d, "total_cycles", usage.total_cycles);
     562                 :          0 :                 rte_tel_data_add_dict_uint(info->d, "busy_cycles", usage.busy_cycles);
     563                 :          0 :                 format_usage_ratio(ratio_str, sizeof(ratio_str), &usage);
     564                 :          0 :                 rte_tel_data_add_dict_string(info->d, "usage_ratio", ratio_str);
     565                 :            :         }
     566                 :            : 
     567                 :            :         /* Return non-zero positive value to stop iterating over lcore_id. */
     568                 :            :         return 1;
     569                 :            : }
     570                 :            : 
     571                 :            : static int
     572                 :          0 : handle_lcore_info(const char *cmd __rte_unused, const char *params, struct rte_tel_data *d)
     573                 :            : {
     574                 :          0 :         struct lcore_telemetry_info info = { .d = d };
     575                 :            :         unsigned long lcore_id;
     576                 :            :         char *endptr;
     577                 :            : 
     578         [ #  # ]:          0 :         if (params == NULL)
     579                 :            :                 return -EINVAL;
     580                 :          0 :         errno = 0;
     581                 :          0 :         lcore_id = strtoul(params, &endptr, 10);
     582         [ #  # ]:          0 :         if (errno)
     583                 :          0 :                 return -errno;
     584   [ #  #  #  #  :          0 :         if (*params == '\0' || *endptr != '\0' || lcore_id >= RTE_MAX_LCORE)
                   #  # ]
     585                 :            :                 return -EINVAL;
     586                 :            : 
     587                 :          0 :         info.lcore_id = lcore_id;
     588                 :            : 
     589                 :          0 :         return rte_lcore_iterate(lcore_telemetry_info_cb, &info);
     590                 :            : }
     591                 :            : 
     592                 :            : struct lcore_telemetry_usage {
     593                 :            :         struct rte_tel_data *lcore_ids;
     594                 :            :         struct rte_tel_data *total_cycles;
     595                 :            :         struct rte_tel_data *busy_cycles;
     596                 :            :         struct rte_tel_data *usage_ratio;
     597                 :            : };
     598                 :            : 
     599                 :            : static int
     600         [ #  # ]:          0 : lcore_telemetry_usage_cb(unsigned int lcore_id, void *arg)
     601                 :            : {
     602                 :            :         char ratio_str[RTE_TEL_MAX_STRING_LEN];
     603                 :            :         struct lcore_telemetry_usage *u = arg;
     604                 :            :         struct rte_lcore_usage usage;
     605                 :            :         rte_lcore_usage_cb usage_cb;
     606                 :            : 
     607                 :            :         /* The callback may not set all the fields in the structure, so clear it here. */
     608                 :            :         memset(&usage, 0, sizeof(usage));
     609                 :            :         /* Guard against concurrent modification of lcore_usage_cb. */
     610                 :          0 :         usage_cb = lcore_usage_cb;
     611   [ #  #  #  # ]:          0 :         if (usage_cb != NULL && usage_cb(lcore_id, &usage) == 0) {
     612                 :          0 :                 rte_tel_data_add_array_uint(u->lcore_ids, lcore_id);
     613                 :          0 :                 rte_tel_data_add_array_uint(u->total_cycles, usage.total_cycles);
     614                 :          0 :                 rte_tel_data_add_array_uint(u->busy_cycles, usage.busy_cycles);
     615                 :          0 :                 format_usage_ratio(ratio_str, sizeof(ratio_str), &usage);
     616                 :          0 :                 rte_tel_data_add_array_string(u->usage_ratio, ratio_str);
     617                 :            :         }
     618                 :            : 
     619                 :          0 :         return 0;
     620                 :            : }
     621                 :            : 
     622                 :            : static int
     623                 :          0 : handle_lcore_usage(const char *cmd __rte_unused, const char *params __rte_unused,
     624                 :            :         struct rte_tel_data *d)
     625                 :            : {
     626                 :            :         struct lcore_telemetry_usage usage;
     627                 :            :         struct rte_tel_data *total_cycles;
     628                 :            :         struct rte_tel_data *busy_cycles;
     629                 :            :         struct rte_tel_data *usage_ratio;
     630                 :            :         struct rte_tel_data *lcore_ids;
     631                 :            : 
     632                 :          0 :         lcore_ids = rte_tel_data_alloc();
     633                 :          0 :         total_cycles = rte_tel_data_alloc();
     634                 :          0 :         busy_cycles = rte_tel_data_alloc();
     635                 :          0 :         usage_ratio = rte_tel_data_alloc();
     636         [ #  # ]:          0 :         if (lcore_ids == NULL || total_cycles == NULL || busy_cycles == NULL ||
     637         [ #  # ]:          0 :             usage_ratio == NULL) {
     638                 :          0 :                 rte_tel_data_free(lcore_ids);
     639                 :          0 :                 rte_tel_data_free(total_cycles);
     640                 :          0 :                 rte_tel_data_free(busy_cycles);
     641                 :          0 :                 rte_tel_data_free(usage_ratio);
     642                 :          0 :                 return -ENOMEM;
     643                 :            :         }
     644                 :            : 
     645                 :          0 :         rte_tel_data_start_dict(d);
     646                 :          0 :         rte_tel_data_start_array(lcore_ids, RTE_TEL_UINT_VAL);
     647                 :          0 :         rte_tel_data_start_array(total_cycles, RTE_TEL_UINT_VAL);
     648                 :          0 :         rte_tel_data_start_array(busy_cycles, RTE_TEL_UINT_VAL);
     649                 :          0 :         rte_tel_data_start_array(usage_ratio, RTE_TEL_STRING_VAL);
     650                 :          0 :         rte_tel_data_add_dict_container(d, "lcore_ids", lcore_ids, 0);
     651                 :          0 :         rte_tel_data_add_dict_container(d, "total_cycles", total_cycles, 0);
     652                 :          0 :         rte_tel_data_add_dict_container(d, "busy_cycles", busy_cycles, 0);
     653                 :          0 :         rte_tel_data_add_dict_container(d, "usage_ratio", usage_ratio, 0);
     654                 :          0 :         usage.lcore_ids = lcore_ids;
     655                 :          0 :         usage.total_cycles = total_cycles;
     656                 :          0 :         usage.busy_cycles = busy_cycles;
     657                 :          0 :         usage.usage_ratio = usage_ratio;
     658                 :            : 
     659                 :          0 :         return rte_lcore_iterate(lcore_telemetry_usage_cb, &usage);
     660                 :            : }
     661                 :            : 
     662                 :        235 : RTE_INIT(lcore_telemetry)
     663                 :            : {
     664                 :        235 :         rte_telemetry_register_cmd("/eal/lcore/list", handle_lcore_list,
     665                 :            :                 "List of lcore ids. Takes no parameters");
     666                 :        235 :         rte_telemetry_register_cmd("/eal/lcore/info", handle_lcore_info,
     667                 :            :                 "Returns lcore info. Parameters: int lcore_id");
     668                 :        235 :         rte_telemetry_register_cmd("/eal/lcore/usage", handle_lcore_usage,
     669                 :            :                 "Returns lcore cycles usage. Takes no parameters");
     670                 :        235 : }
     671                 :            : #endif /* !RTE_EXEC_ENV_WINDOWS */

Generated by: LCOV version 1.14