/* * BSD LICENSE * * Copyright(c) 2016-2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * Neither the name of Intel Corporation nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include /**< gettimeofday() */ #include "common.h" #include "rdt.h" struct rdtset g_cfg; int str_to_cpuset(const char *cpustr, const unsigned cpustr_len, cpu_set_t *cpuset) { unsigned idx, min, max; char *buff = malloc(cpustr_len + 1); char *end = NULL; const char *str = buff; int ret = 0; if (NULL == buff || NULL == cpustr || NULL == cpuset || 0 == cpustr_len) goto err; memcpy(buff, cpustr, cpustr_len); buff[cpustr_len] = 0; CPU_ZERO(cpuset); while (isblank(*str)) str++; /* only digit is qualify for start point */ if (!isdigit(*str) || *str == '\0') goto err; min = CPU_SETSIZE; do { /* go ahead to the first digit */ while (isblank(*str)) str++; if (!isdigit(*str)) goto err; /* get the digit value */ errno = 0; idx = strtoul(str, &end, 10); if (errno != 0 || end == NULL || end == str || idx >= CPU_SETSIZE) goto err; /* go ahead to separator '-',',' */ while (isblank(*end)) end++; if (*end == '-') { if (min == CPU_SETSIZE) min = idx; else /* avoid continuous '-' */ goto err; } else if (*end == ',' || *end == 0) { max = idx; if (min == CPU_SETSIZE) min = idx; for (idx = MIN(min, max); idx <= MAX(min, max); idx++) CPU_SET(idx, cpuset); min = CPU_SETSIZE; } else goto err; str = end + 1; } while (*end != '\0'); ret = end - buff; free(buff); return ret; err: if (buff != NULL) free(buff); return -EINVAL; } void cpuset_to_str(char *cpustr, const unsigned cpustr_len, const cpu_set_t *cpuset) { unsigned len = 0, j = 0; memset(cpustr, 0, cpustr_len); /* Generate CPU list */ for (j = 0; j < CPU_SETSIZE; j++) { if (CPU_ISSET(j, cpuset) != 1) continue; len += snprintf(cpustr + len, cpustr_len - len - 1, "%u,", j); if (len >= cpustr_len - 1) { len = cpustr_len; memcpy(cpustr + cpustr_len - 4, "...", 3); break; } } /* Remove trailing separator */ cpustr[len - 1] = 0; } /** * @brief Function to check if a value is already contained in a table * * @param tab table of values to check * @param size size of the table * @param val value to search for * * @return If the value is already in the table * @retval 1 if value if found * @retval 0 if value is not found */ static int isdup(const uint64_t *tab, const unsigned size, const uint64_t val) { unsigned i; for (i = 0; i < size; i++) if (tab[i] == val) return 1; return 0; } /** * @brief Converts string into 64-bit unsigned number. * * Numbers can be in decimal or hexadecimal format. * On error, this functions causes process to exit with FAILURE code. * * @param s string to be converted into 64-bit unsigned number * * @return Numeric value of the string representing the number */ static uint64_t strtouint64(const char *s) { const char *str = s; int base = 10; uint64_t n = 0; char *endptr = NULL; if (s == NULL) exit(EXIT_FAILURE); if (strncasecmp(s, "0x", 2) == 0) { base = 16; s += 2; } n = strtoull(s, &endptr, base); if (!(*s != '\0' && *endptr == '\0')) { printf("Error converting '%s' to unsigned number!\n", str); exit(EXIT_FAILURE); } return n; } unsigned strlisttotab(char *s, uint64_t *tab, const unsigned max) { unsigned index = 0; char *saveptr = NULL; if (s == NULL || tab == NULL || max == 0) return index; for (;;) { char *p = NULL; char *token = NULL; token = strtok_r(s, ",", &saveptr); if (token == NULL) break; s = NULL; /* get rid of leading spaces & skip empty tokens */ while (isspace(*token)) token++; if (*token == '\0') continue; p = strchr(token, '-'); if (p != NULL) { /** * range of numbers provided * example: 1-5 or 12-9 */ uint64_t n, start, end; *p = '\0'; start = strtouint64(token); end = strtouint64(p + 1); if (start > end) { /** * no big deal just swap start with end */ n = start; start = end; end = n; } for (n = start; n <= end; n++) { if (!(isdup(tab, index, n))) { tab[index] = n; index++; } if (index >= max) return index; } } else { /** * single number provided here * remove duplicates if necessary */ uint64_t val = strtouint64(token); if (!(isdup(tab, index, val))) { tab[index] = val; index++; } if (index >= max) return index; } } return index; } uint64_t get_time_usec(void) { struct timeval tv; gettimeofday(&tv, NULL); return ((uint64_t)tv.tv_usec) + ((uint64_t)tv.tv_sec * 1000000L); }