LCOV - code coverage report
Current view: top level - spdk/lib/util - cpuset.c (source / functions) Hit Total Coverage
Test: Combined Lines: 179 186 96.2 %
Date: 2024-11-17 16:26:13 Functions: 19 19 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 225 446 50.4 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright (C) 2017 Intel Corporation. All rights reserved.
       3                 :            :  *   All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "spdk/cpuset.h"
       7                 :            : #include "spdk/log.h"
       8                 :            : 
       9                 :            : struct spdk_cpuset *
      10                 :         27 : spdk_cpuset_alloc(void)
      11                 :            : {
      12                 :         27 :         return (struct spdk_cpuset *)calloc(1, sizeof(struct spdk_cpuset));
      13                 :            : }
      14                 :            : 
      15                 :            : void
      16                 :         27 : spdk_cpuset_free(struct spdk_cpuset *set)
      17                 :            : {
      18                 :         27 :         free(set);
      19                 :         27 : }
      20                 :            : 
      21                 :            : bool
      22                 :       1157 : spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
      23                 :            : {
      24   [ +  +  #  # ]:       1157 :         assert(set1 != NULL);
      25   [ +  +  #  # ]:       1157 :         assert(set2 != NULL);
      26   [ +  +  +  +  :       1157 :         return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
             +  -  +  - ]
      27                 :            : }
      28                 :            : 
      29                 :            : void
      30                 :      29317 : spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
      31                 :            : {
      32   [ +  +  #  # ]:      29317 :         assert(dst != NULL);
      33   [ +  +  #  # ]:      29317 :         assert(src != NULL);
      34   [ +  +  +  +  :      29317 :         memcpy(&dst->cpus, &src->cpus, sizeof(src->cpus));
             +  -  +  - ]
      35                 :      29317 : }
      36                 :            : 
      37                 :            : void
      38                 :       3006 : spdk_cpuset_negate(struct spdk_cpuset *set)
      39                 :            : {
      40                 :            :         unsigned int i;
      41   [ +  +  #  # ]:       3006 :         assert(set != NULL);
      42         [ +  + ]:     387537 :         for (i = 0; i < sizeof(set->cpus); i++) {
      43   [ +  -  +  -  :     384531 :                 set->cpus[i] = ~set->cpus[i];
          +  -  +  -  +  
                -  +  - ]
      44                 :      37651 :         }
      45                 :       3006 : }
      46                 :            : 
      47                 :            : void
      48                 :       7352 : spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
      49                 :            : {
      50                 :            :         unsigned int i;
      51   [ +  +  #  # ]:       7352 :         assert(dst != NULL);
      52   [ +  +  #  # ]:       7352 :         assert(src != NULL);
      53         [ +  + ]:     948408 :         for (i = 0; i < sizeof(src->cpus); i++) {
      54   [ +  -  +  -  :     941056 :                 dst->cpus[i] &= src->cpus[i];
          +  -  +  -  +  
                -  +  - ]
      55                 :      49792 :         }
      56                 :       7352 : }
      57                 :            : 
      58                 :            : void
      59                 :       2443 : spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
      60                 :            : {
      61                 :            :         unsigned int i;
      62   [ +  +  #  # ]:       2443 :         assert(dst != NULL);
      63   [ +  +  #  # ]:       2443 :         assert(src != NULL);
      64         [ +  + ]:     315147 :         for (i = 0; i < sizeof(src->cpus); i++) {
      65   [ +  -  +  -  :     312704 :                 dst->cpus[i] |= src->cpus[i];
          +  -  +  -  +  
                -  +  - ]
      66                 :      29568 :         }
      67                 :       2443 : }
      68                 :            : 
      69                 :            : void
      70                 :       6944 : spdk_cpuset_xor(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
      71                 :            : {
      72                 :            :         unsigned int i;
      73   [ +  +  #  # ]:       6944 :         assert(dst != NULL);
      74   [ +  +  #  # ]:       6944 :         assert(src != NULL);
      75         [ +  + ]:     895776 :         for (i = 0; i < sizeof(src->cpus); i++) {
      76   [ +  -  +  -  :     888832 :                 dst->cpus[i] ^= src->cpus[i];
          +  -  +  -  +  
                -  +  - ]
      77                 :      50432 :         }
      78                 :       6944 : }
      79                 :            : 
      80                 :            : void
      81                 :      18639 : spdk_cpuset_zero(struct spdk_cpuset *set)
      82                 :            : {
      83   [ +  +  #  # ]:      18639 :         assert(set != NULL);
      84   [ +  +  +  - ]:      18639 :         memset(set->cpus, 0, sizeof(set->cpus));
      85                 :      18639 : }
      86                 :            : 
      87                 :            : void
      88                 :      60651 : spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
      89                 :            : {
      90   [ +  +  #  # ]:      60651 :         assert(set != NULL);
      91   [ +  +  #  # ]:      60651 :         assert(cpu < sizeof(set->cpus) * 8);
      92   [ +  +  +  + ]:      60651 :         if (state) {
      93   [ +  +  +  -  :      60377 :                 set->cpus[cpu / 8] |= (1U << (cpu % 8));
          +  -  +  -  +  
                -  +  - ]
      94                 :       4807 :         } else {
      95   [ +  +  +  -  :        274 :                 set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
          +  -  +  -  +  
                -  +  - ]
      96                 :            :         }
      97                 :      60651 : }
      98                 :            : 
      99                 :            : bool
     100                 :   33206827 : spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
     101                 :            : {
     102   [ +  +  #  # ]:   33206827 :         assert(set != NULL);
     103   [ +  +  #  # ]:   33206827 :         assert(cpu < sizeof(set->cpus) * 8);
     104   [ +  +  +  -  :   33206827 :         return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
          +  -  +  -  +  
                -  +  - ]
     105                 :            : }
     106                 :            : 
     107                 :            : void
     108                 :       8297 : spdk_cpuset_for_each_cpu(const struct spdk_cpuset *set,
     109                 :            :                          void (*fn)(void *ctx, uint32_t cpu), void *ctx)
     110                 :            : {
     111                 :            :         uint8_t n;
     112                 :            :         unsigned int i, j;
     113         [ +  + ]:    1070313 :         for (i = 0; i < sizeof(set->cpus); i++) {
     114   [ -  +  -  +  :    1062016 :                 n = set->cpus[i];
                   -  + ]
     115         [ +  + ]:    9558144 :                 for (j = 0; j < 8; j++) {
     116   [ +  +  +  +  :    8496128 :                         if (n & (1 << j)) {
                   +  + ]
     117   [ -  +  +  - ]:      15346 :                                 fn(ctx, i * 8 + j);
     118                 :       1684 :                         }
     119                 :     522240 :                 }
     120                 :      65280 :         }
     121                 :       8297 : }
     122                 :            : 
     123                 :            : static void
     124                 :      15246 : count_fn(void *ctx, uint32_t cpu)
     125                 :            : {
     126                 :      15246 :         uint32_t *count = ctx;
     127                 :            : 
     128                 :      15246 :         (*count)++;
     129                 :      15246 : }
     130                 :            : 
     131                 :            : uint32_t
     132                 :       8269 : spdk_cpuset_count(const struct spdk_cpuset *set)
     133                 :            : {
     134                 :       8269 :         uint32_t count = 0;
     135                 :            : 
     136                 :       8269 :         spdk_cpuset_for_each_cpu(set, count_fn, &count);
     137                 :       8269 :         return count;
     138                 :            : }
     139                 :            : 
     140                 :            : const char *
     141                 :       2776 : spdk_cpuset_fmt(struct spdk_cpuset *set)
     142                 :            : {
     143                 :       2776 :         uint32_t lcore, lcore_max = 0;
     144                 :            :         int val, i, n;
     145                 :            :         char *ptr;
     146                 :            :         static const char *hex = "0123456789abcdef";
     147                 :            : 
     148   [ +  +  #  # ]:       2776 :         assert(set != NULL);
     149                 :            : 
     150         [ +  + ]:    2845400 :         for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
     151         [ +  + ]:    2842624 :                 if (spdk_cpuset_get_cpu(set, lcore)) {
     152                 :       9242 :                         lcore_max = lcore;
     153                 :       1286 :                 }
     154                 :     128000 :         }
     155                 :            : 
     156         [ #  # ]:       2776 :         ptr = set->str;
     157         [ #  # ]:       2776 :         n = lcore_max / 8;
     158   [ #  #  #  #  :       2776 :         val = set->cpus[n];
                   #  # ]
     159                 :            : 
     160                 :            :         /* Store first number only if it is not leading zero */
     161         [ +  + ]:       2776 :         if ((val & 0xf0) != 0) {
     162   [ #  #  #  #  :        227 :                 *(ptr++) = hex[(val & 0xf0) >> 4];
          #  #  #  #  #  
                      # ]
     163                 :         20 :         }
     164   [ #  #  #  #  :       2776 :         *(ptr++) = hex[val & 0x0f];
             #  #  #  # ]
     165                 :            : 
     166   [ +  +  #  #  :       4329 :         for (i = n - 1; i >= 0; i--) {
                   #  # ]
     167   [ #  #  #  #  :       1553 :                 val = set->cpus[i];
                   #  # ]
     168   [ #  #  #  #  :       1553 :                 *(ptr++) = hex[(val & 0xf0) >> 4];
          #  #  #  #  #  
                      # ]
     169   [ #  #  #  #  :       1553 :                 *(ptr++) = hex[val & 0x0f];
             #  #  #  # ]
     170                 :        129 :         }
     171         [ #  # ]:       2776 :         *ptr = '\0';
     172                 :            : 
     173         [ #  # ]:       2776 :         return set->str;
     174                 :            : }
     175                 :            : 
     176                 :            : static int
     177                 :       3473 : hex_value(uint8_t c)
     178                 :            : {
     179                 :            : #define V(x, y) [x] = y + 1
     180                 :            :         static const int8_t val[256] = {
     181                 :            :                 V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
     182                 :            :                 V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
     183                 :            :                 V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
     184                 :            :                 V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
     185                 :            :         };
     186                 :            : #undef V
     187                 :            : 
     188   [ +  -  +  -  :       3473 :         return val[c] - 1;
             +  -  +  - ]
     189                 :            : }
     190                 :            : 
     191                 :            : static int
     192                 :         62 : parse_list(const char *mask, struct spdk_cpuset *set)
     193                 :            : {
     194                 :         51 :         char *end;
     195                 :         62 :         const char *ptr = mask;
     196                 :            :         uint32_t lcore;
     197                 :            :         uint32_t lcore_min, lcore_max;
     198                 :            : 
     199                 :         62 :         spdk_cpuset_zero(set);
     200                 :         62 :         lcore_min = UINT32_MAX;
     201                 :            : 
     202         [ #  # ]:         62 :         ptr++;
     203                 :         62 :         end = (char *)ptr;
     204                 :         11 :         do {
     205   [ -  +  #  #  :        116 :                 while (isblank(*ptr)) {
          #  #  #  #  #  
                      # ]
     206         [ #  # ]:          0 :                         ptr++;
     207                 :            :                 }
     208   [ +  +  +  +  :        116 :                 if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
          +  +  +  +  #  
          #  #  #  #  #  
                   #  # ]
     209                 :         20 :                         goto invalid_character;
     210                 :            :                 }
     211                 :            : 
     212         [ #  # ]:         96 :                 errno = 0;
     213         [ -  + ]:         96 :                 lcore = strtoul(ptr, &end, 10);
     214   [ +  +  #  # ]:         96 :                 if (errno) {
     215                 :          4 :                         SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
     216                 :          4 :                         return -1;
     217                 :            :                 }
     218                 :            : 
     219         [ +  + ]:         92 :                 if (lcore >= sizeof(set->cpus) * 8) {
     220                 :          4 :                         SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
     221                 :          4 :                         return -1;
     222                 :            :                 }
     223                 :            : 
     224   [ -  +  #  #  :         88 :                 while (isblank(*end)) {
          #  #  #  #  #  
                      # ]
     225         [ #  # ]:          0 :                         end++;
     226                 :            :                 }
     227                 :            : 
     228   [ +  +  #  # ]:         88 :                 if (*end == '-') {
     229                 :         24 :                         lcore_min = lcore;
     230   [ +  +  +  +  :         70 :                 } else if (*end == ',' || *end == ']') {
             #  #  #  # ]
     231                 :         64 :                         lcore_max = lcore;
     232         [ +  + ]:         64 :                         if (lcore_min == UINT32_MAX) {
     233                 :         44 :                                 lcore_min = lcore;
     234                 :          2 :                         }
     235         [ +  + ]:         64 :                         if (lcore_min > lcore_max) {
     236                 :          4 :                                 SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
     237                 :            :                                             lcore_min, lcore_max);
     238                 :          4 :                                 return -1;
     239                 :            :                         }
     240         [ +  + ]:       4760 :                         for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
     241                 :       4700 :                                 spdk_cpuset_set_cpu(set, lcore, true);
     242                 :       1166 :                         }
     243                 :         60 :                         lcore_min = UINT32_MAX;
     244                 :          6 :                 } else {
     245                 :          0 :                         goto invalid_character;
     246                 :            :                 }
     247                 :            : 
     248         [ #  # ]:         84 :                 ptr = end + 1;
     249                 :            : 
     250   [ +  +  #  # ]:         84 :         } while (*end != ']');
     251                 :            : 
     252                 :         30 :         return 0;
     253                 :            : 
     254                 :         15 : invalid_character:
     255   [ +  +  #  # ]:         20 :         if (*end == '\0') {
     256                 :          4 :                 SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
     257                 :          1 :         } else {
     258         [ #  # ]:         16 :                 SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
     259                 :            :         }
     260                 :         20 :         return -1;
     261                 :         11 : }
     262                 :            : 
     263                 :            : static int
     264                 :        557 : parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
     265                 :            : {
     266                 :            :         int i, j;
     267                 :            :         char c;
     268                 :            :         int val;
     269                 :        557 :         uint32_t lcore = 0;
     270                 :            : 
     271   [ +  +  +  +  :        557 :         if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
          +  +  +  -  +  
          -  +  +  +  -  
             +  -  -  + ]
     272         [ +  - ]:        341 :                 mask += 2;
     273                 :        341 :                 len -= 2;
     274                 :         29 :         }
     275                 :            : 
     276                 :        557 :         spdk_cpuset_zero(set);
     277   [ +  +  +  - ]:       4362 :         for (i = len - 1; i >= 0; i--) {
     278   [ +  -  +  - ]:       3805 :                 c = mask[i];
     279         [ +  + ]:       3805 :                 if (c == ',') {
     280                 :            :                         /* Linux puts comma delimiters in its cpumasks, just skip them. */
     281                 :        332 :                         continue;
     282                 :            :                 }
     283                 :       3473 :                 val = hex_value(c);
     284         [ +  + ]:       3473 :                 if (val < 0) {
     285                 :            :                         /* Invalid character */
     286                 :          0 :                         SPDK_ERRLOG("Invalid character in core mask '%s' (%c)\n", mask, c);
     287                 :          0 :                         return -1;
     288                 :            :                 }
     289   [ +  +  +  +  :      17365 :                 for (j = 0; j < 4 && lcore < SPDK_CPUSET_SIZE; j++, lcore++) {
                   +  - ]
     290   [ +  +  +  +  :      13892 :                         if ((1 << j) & val) {
                   +  + ]
     291                 :       1585 :                                 spdk_cpuset_set_cpu(set, lcore, true);
     292                 :        207 :                         }
     293                 :        924 :                 }
     294                 :        231 :         }
     295                 :            : 
     296                 :        557 :         return 0;
     297                 :         35 : }
     298                 :            : 
     299                 :            : int
     300                 :        631 : spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
     301                 :            : {
     302                 :            :         int ret;
     303                 :            :         size_t len;
     304                 :            : 
     305   [ +  +  +  + ]:        631 :         if (mask == NULL || set == NULL) {
     306                 :          8 :                 return -1;
     307                 :            :         }
     308                 :            : 
     309   [ +  +  +  -  :        623 :         while (isblank(*mask)) {
          +  -  +  -  -  
                      + ]
     310         [ #  # ]:          0 :                 mask++;
     311                 :            :         }
     312                 :            : 
     313         [ +  + ]:        623 :         len = strlen(mask);
     314   [ +  +  +  +  :        623 :         while (len > 0 && isblank(mask[len - 1])) {
          +  -  +  -  +  
             -  +  -  -  
                      + ]
     315                 :          0 :                 len--;
     316                 :            :         }
     317                 :            : 
     318         [ +  + ]:        623 :         if (len == 0) {
     319                 :          4 :                 return -1;
     320                 :            :         }
     321                 :            : 
     322   [ +  +  +  -  :        619 :         if (mask[0] == '[') {
                   -  + ]
     323                 :         62 :                 ret = parse_list(mask, set);
     324                 :         11 :         } else {
     325                 :        557 :                 ret = parse_mask(mask, set, len);
     326                 :            :         }
     327                 :            : 
     328                 :        619 :         return ret;
     329                 :         49 : }

Generated by: LCOV version 1.15