[24.03,v2,2/5] arg_parser: add new coremask parsing API
Checks
Commit Message
Add new coremask parsing API. This API behaves similarly to the corelist
parsing API, parsing the coremask string, filling its values into the
cores array.
The API also returns a 'count' which corresponds to the total number of
cores in the coremask string.
Signed-off-by: Euan Bourke <euan.bourke@intel.com>
---
lib/arg_parser/arg_parser.c | 57 +++++++++++++++++++++++++++++++++
lib/arg_parser/rte_arg_parser.h | 33 +++++++++++++++++++
lib/arg_parser/version.map | 1 +
3 files changed, 91 insertions(+)
@@ -11,6 +11,9 @@
#include <rte_arg_parser.h>
#include <rte_common.h>
+#define BITS_PER_HEX 4
+#define MAX_COREMASK_SIZE ((UINT16_MAX + 1) / BITS_PER_HEX)
+
struct core_bits {
uint8_t bits[(UINT16_MAX + 1)/CHAR_BIT];
@@ -57,6 +60,15 @@ corebits_to_array(struct core_bits *mask, uint16_t *cores, size_t max_cores)
return mask->total_bits_set;
}
+static int xdigit2val(unsigned char c)
+{
+ if (isdigit(c))
+ return c - '0';
+ else if (isupper(c))
+ return c - 'A' + 10;
+ else
+ return c - 'a' + 10;
+}
int
rte_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len)
@@ -111,3 +123,48 @@ rte_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len)
return total_count;
}
+
+int
+rte_parse_coremask(const char *coremask, uint16_t *cores, uint32_t cores_len)
+{
+ struct core_bits *mask = malloc(sizeof(struct core_bits));
+ if (mask == NULL)
+ return -1;
+ memset(mask, 0, sizeof(struct core_bits));
+
+ /* Remove all blank characters ahead and after .
+ * Remove 0x/0X if exists.
+ */
+ while (isblank(*coremask))
+ coremask++;
+ if (coremask[0] == '0' && ((coremask[1] == 'x') || (coremask[1] == 'X')))
+ coremask += 2;
+
+ int32_t i = strlen(coremask);
+ while ((i > 0) && isblank(coremask[i - 1]))
+ i--;
+ if (i == 0 || i > MAX_COREMASK_SIZE)
+ return -1;
+
+ uint32_t idx = 0;
+
+ for (i = i - 1; i >= 0; i--) {
+ int val;
+ char c = coremask[i];
+
+ if (isxdigit(c) == 0)
+ return -1;
+
+ val = xdigit2val(c);
+
+ for (uint8_t j = 0; j < BITS_PER_HEX; j++, idx++) {
+ if ((1 << j) & val)
+ set_core_bit(mask, idx);
+ }
+ }
+
+ uint32_t total_count = corebits_to_array(mask, cores, cores_len);
+ free(mask);
+
+ return total_count;
+}
@@ -57,6 +57,39 @@ __rte_experimental
int
rte_parse_corelist(const char *corelist, uint16_t *cores, uint32_t cores_len);
+/**
+ * Convert a string describing a bitmask of core ids into an array of core ids.
+ *
+ * On success, the passed array is filled with the core ids present in the
+ * bitmask up to the "cores_len", and the number of elements added into the array is returned.
+ * For example, passing a 0xA "coremask" results in an array of [1, 3]
+ * and would return 2.
+ *
+ * Like the snprintf function for strings, if the length of the input array is
+ * insufficient to hold the number of cores in the "coresmask", the input array is
+ * filled to capacity and the return value is the number of elements which would
+ * be returned if the array had been big enough.
+ * Function can also be called with a NULL array and 0 "cores_len" to find out
+ * the "cores_len" required.
+ *
+ * @param coremask
+ * A string containing a bitmask of core ids.
+ * @param cores
+ * An array where to store the core ids.
+ * Array can be NULL if "cores_len" is 0.
+ * @param cores_len
+ * The length of the "cores" array.
+ * If the size is smaller than that needed to hold all cores from "coremask",
+ * only "cores_len" elements will be written to the array.
+ * @return
+ * n: the number of unique cores present in "coremask".
+ * -1 if the string was invalid.
+ * NOTE: if n > "cores_len", then only "cores_len" elements in the "cores" array are valid.
+ */
+__rte_experimental
+int
+rte_parse_coremask(const char *coremask, uint16_t *cores, uint32_t cores_len);
+
#ifdef __cplusplus
}
@@ -7,4 +7,5 @@ EXPERIMENTAL {
# added in 24.03
rte_parse_corelist;
+ rte_parse_coremask;
};