-static int isdup(const uint64_t *nums, size_t size, uint64_t val) {
- for (size_t i = 0; i < size; i++)
- if (nums[i] == val)
- return 1;
- return 0;
-}
-
-static int strtouint64(const char *s, uint64_t *n) {
- char *endptr = NULL;
-
- assert(s != NULL);
- assert(n != NULL);
-
- *n = strtoull(s, &endptr, 0);
-
- if (!(*s != '\0' && *endptr == '\0')) {
- DEBUG(RDT_PLUGIN ": Error converting '%s' to unsigned number.", s);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * NAME
- * strlisttonums
- *
- * DESCRIPTION
- * Converts string of characters representing list of numbers into array of
- * numbers. Allowed formats are:
- * 0,1,2,3
- * 0-10,20-18
- * 1,3,5-8,10,0x10-12
- *
- * Numbers can be in decimal or hexadecimal format.
- *
- * PARAMETERS
- * `s' String representing list of unsigned numbers.
- * `nums' Array to put converted numeric values into.
- * `max' Maximum number of elements that nums can accommodate.
- *
- * RETURN VALUE
- * Number of elements placed into nums.
- */
-static size_t strlisttonums(char *s, uint64_t *nums, size_t max) {
- int ret;
- size_t index = 0;
- char *saveptr = NULL;
-
- if (s == NULL || nums == NULL || max == 0)
- return index;
-
- for (;;) {
- char *p = NULL;
- char *token = NULL;
-
- token = strtok_r(s, ",", &saveptr);
- if (token == NULL)
- break;
-
- s = NULL;
-
- while (isspace(*token))
- token++;
- if (*token == '\0')
- continue;
-
- p = strchr(token, '-');
- if (p != NULL) {
- uint64_t n, start, end;
- *p = '\0';
- ret = strtouint64(token, &start);
- if (ret < 0)
- return 0;
- ret = strtouint64(p + 1, &end);
- if (ret < 0)
- return 0;
- if (start > end) {
- return 0;
- }
- for (n = start; n <= end; n++) {
- if (!(isdup(nums, index, n))) {
- nums[index] = n;
- index++;
- }
- if (index >= max)
- return index;
- }
- } else {
- uint64_t val;
-
- ret = strtouint64(token, &val);
- if (ret < 0)
- return 0;
-
- if (!(isdup(nums, index, val))) {
- nums[index] = val;
- index++;
- }
- if (index >= max)
- return index;
- }
- }
-
- return index;
-}
-
-/*
- * NAME
- * cgroup_cmp
- *
- * DESCRIPTION
- * Function to compare cores in 2 core groups.
- *
- * PARAMETERS
- * `cg_a' Pointer to core group a.
- * `cg_b' Pointer to core group b.
- *
- * RETURN VALUE
- * 1 if both groups contain the same cores
- * 0 if none of their cores match
- * -1 if some but not all cores match
- */
-static int cgroup_cmp(const rdt_core_group_t *cg_a,
- const rdt_core_group_t *cg_b) {
- int found = 0;
-
- assert(cg_a != NULL);
- assert(cg_b != NULL);
-
- const int sz_a = cg_a->num_cores;
- const int sz_b = cg_b->num_cores;
- const unsigned *tab_a = cg_a->cores;
- const unsigned *tab_b = cg_b->cores;
-
- for (int i = 0; i < sz_a; i++) {
- for (int j = 0; j < sz_b; j++)
- if (tab_a[i] == tab_b[j])
- found++;
- }
- /* if no cores are the same */
- if (!found)
- return 0;
- /* if group contains same cores */
- if (sz_a == sz_b && sz_b == found)
- return 1;
- /* if not all cores are the same */
- return -1;
-}
-
-static int cgroup_set(rdt_core_group_t *cg, char *desc, uint64_t *cores,
- size_t num_cores) {
- assert(cg != NULL);
- assert(desc != NULL);
- assert(cores != NULL);
- assert(num_cores > 0);
-
- cg->cores = calloc(num_cores, sizeof(unsigned));
- if (cg->cores == NULL) {
- ERROR(RDT_PLUGIN ": Error allocating core group table");
- return -ENOMEM;
- }
- cg->num_cores = num_cores;
- cg->desc = strdup(desc);
- if (cg->desc == NULL) {
- ERROR(RDT_PLUGIN ": Error allocating core group description");
- sfree(cg->cores);
- return -ENOMEM;
- }
-
- for (size_t i = 0; i < num_cores; i++)
- cg->cores[i] = (unsigned)cores[i];
-
- return 0;
-}
-
-/*
- * NAME
- * oconfig_to_cgroups
- *
- * DESCRIPTION
- * Function to set the descriptions and cores for each core group.
- * Takes a config option containing list of strings that are used to set
- * core group values.
- *
- * PARAMETERS
- * `item' Config option containing core groups.
- * `groups' Table of core groups to set values in.
- * `max_groups' Maximum number of core groups allowed.
- *
- * RETURN VALUE
- * On success, the number of core groups set up. On error, appropriate
- * negative error value.
- */
-static int oconfig_to_cgroups(oconfig_item_t *item, rdt_core_group_t *groups,
- size_t max_groups) {
- int index = 0;
-
- assert(groups != NULL);
- assert(max_groups > 0);
- assert(item != NULL);
-
- for (int j = 0; j < item->values_num; j++) {
- int ret;
- size_t n;
- uint64_t cores[RDT_MAX_CORES] = {0};
- char value[DATA_MAX_NAME_LEN];
-
- if ((item->values[j].value.string == NULL) ||
- (strlen(item->values[j].value.string) == 0))
- continue;
-
- sstrncpy(value, item->values[j].value.string, sizeof(value));
-
- n = strlisttonums(value, cores, STATIC_ARRAY_SIZE(cores));
- if (n == 0) {
- ERROR(RDT_PLUGIN ": Error parsing core group (%s)",
- item->values[j].value.string);
- return -EINVAL;
- }
-
- /* set core group info */
- ret = cgroup_set(&groups[index], item->values[j].value.string, cores, n);
- if (ret < 0)
- return ret;
-
- index++;
-
- if (index >= max_groups) {
- WARNING(RDT_PLUGIN ": Too many core groups configured");
- return index;
- }
- }
-
- return index;
-}
-