numam-spdk/lib/util/cpuset.c
Darek Stojaczyk 60d487877a util/cpuset: use dst & src parameter names
Declaractions for those functions already have dst
and src as param names, but definitions use set1 and
set2, which doesn't really tell which one is which.

My IDE actually gives me tooltips with param names
from definitions and it would be much easier to see
"dst" and "src" in there.

Change-Id: I45013cf27fc95f69cb2c776fb1b6701c5e60e373
Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/455163
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
2019-05-23 07:00:34 +00:00

342 lines
7.4 KiB
C

/*-
* BSD LICENSE
*
* Copyright(c) 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 "spdk/cpuset.h"
#include "spdk/log.h"
struct spdk_cpuset {
char str[SPDK_CPUSET_SIZE / 4 + 1];
uint8_t cpus[SPDK_CPUSET_SIZE / 8];
};
struct spdk_cpuset *
spdk_cpuset_alloc(void)
{
return (struct spdk_cpuset *)calloc(sizeof(struct spdk_cpuset), 1);
}
void
spdk_cpuset_free(struct spdk_cpuset *set)
{
free(set);
}
bool
spdk_cpuset_equal(const struct spdk_cpuset *set1, const struct spdk_cpuset *set2)
{
assert(set1 != NULL);
assert(set2 != NULL);
return memcmp(set1->cpus, set2->cpus, sizeof(set2->cpus)) == 0;
}
void
spdk_cpuset_copy(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
{
assert(dst != NULL);
assert(src != NULL);
memcpy(&dst->cpus, &src->cpus, sizeof(src->cpus));
}
void
spdk_cpuset_negate(struct spdk_cpuset *set)
{
unsigned int i;
assert(set != NULL);
for (i = 0; i < sizeof(set->cpus); i++) {
set->cpus[i] = ~set->cpus[i];
}
}
void
spdk_cpuset_and(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
{
unsigned int i;
assert(dst != NULL);
assert(src != NULL);
for (i = 0; i < sizeof(src->cpus); i++) {
dst->cpus[i] &= src->cpus[i];
}
}
void
spdk_cpuset_or(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
{
unsigned int i;
assert(dst != NULL);
assert(src != NULL);
for (i = 0; i < sizeof(src->cpus); i++) {
dst->cpus[i] |= src->cpus[i];
}
}
void
spdk_cpuset_xor(struct spdk_cpuset *dst, const struct spdk_cpuset *src)
{
unsigned int i;
assert(dst != NULL);
assert(src != NULL);
for (i = 0; i < sizeof(src->cpus); i++) {
dst->cpus[i] ^= src->cpus[i];
}
}
void
spdk_cpuset_zero(struct spdk_cpuset *set)
{
assert(set != NULL);
memset(set->cpus, 0, sizeof(set->cpus));
}
void
spdk_cpuset_set_cpu(struct spdk_cpuset *set, uint32_t cpu, bool state)
{
assert(set != NULL);
assert(cpu < sizeof(set->cpus) * 8);
if (state) {
set->cpus[cpu / 8] |= (1U << (cpu % 8));
} else {
set->cpus[cpu / 8] &= ~(1U << (cpu % 8));
}
}
bool
spdk_cpuset_get_cpu(const struct spdk_cpuset *set, uint32_t cpu)
{
assert(set != NULL);
assert(cpu < sizeof(set->cpus) * 8);
return (set->cpus[cpu / 8] >> (cpu % 8)) & 1U;
}
uint32_t
spdk_cpuset_count(const struct spdk_cpuset *set)
{
uint32_t count = 0;
uint8_t n;
unsigned int i;
for (i = 0; i < sizeof(set->cpus); i++) {
n = set->cpus[i];
while (n) {
n &= (n - 1);
count++;
}
}
return count;
}
const char *
spdk_cpuset_fmt(struct spdk_cpuset *set)
{
uint32_t lcore, lcore_max = 0;
int val, i, n;
char *ptr;
static const char *hex = "0123456789abcdef";
assert(set != NULL);
for (lcore = 0; lcore < sizeof(set->cpus) * 8; lcore++) {
if (spdk_cpuset_get_cpu(set, lcore)) {
lcore_max = lcore;
}
}
ptr = set->str;
n = lcore_max / 8;
val = set->cpus[n];
/* Store first number only if it is not leading zero */
if ((val & 0xf0) != 0) {
*(ptr++) = hex[(val & 0xf0) >> 4];
}
*(ptr++) = hex[val & 0x0f];
for (i = n - 1; i >= 0; i--) {
val = set->cpus[i];
*(ptr++) = hex[(val & 0xf0) >> 4];
*(ptr++) = hex[val & 0x0f];
}
*ptr = '\0';
return set->str;
}
static int
hex_value(uint8_t c)
{
#define V(x, y) [x] = y + 1
static const int8_t val[256] = {
V('0', 0), V('1', 1), V('2', 2), V('3', 3), V('4', 4),
V('5', 5), V('6', 6), V('7', 7), V('8', 8), V('9', 9),
V('A', 0xA), V('B', 0xB), V('C', 0xC), V('D', 0xD), V('E', 0xE), V('F', 0xF),
V('a', 0xA), V('b', 0xB), V('c', 0xC), V('d', 0xD), V('e', 0xE), V('f', 0xF),
};
#undef V
return val[c] - 1;
}
static int
parse_list(const char *mask, struct spdk_cpuset *set)
{
char *end;
const char *ptr = mask;
uint32_t lcore;
uint32_t lcore_min, lcore_max;
spdk_cpuset_zero(set);
lcore_min = UINT32_MAX;
ptr++;
end = (char *)ptr;
do {
while (isblank(*ptr)) {
ptr++;
}
if (*ptr == '\0' || *ptr == ']' || *ptr == '-' || *ptr == ',') {
goto invalid_character;
}
errno = 0;
lcore = strtoul(ptr, &end, 10);
if (errno) {
SPDK_ERRLOG("Conversion of core mask in '%s' failed\n", mask);
return -1;
}
if (lcore >= sizeof(set->cpus) * 8) {
SPDK_ERRLOG("Core number %" PRIu32 " is out of range in '%s'\n", lcore, mask);
return -1;
}
while (isblank(*end)) {
end++;
}
if (*end == '-') {
lcore_min = lcore;
} else if (*end == ',' || *end == ']') {
lcore_max = lcore;
if (lcore_min == UINT32_MAX) {
lcore_min = lcore;
}
if (lcore_min > lcore_max) {
SPDK_ERRLOG("Invalid range of CPUs (%" PRIu32 " > %" PRIu32 ")\n",
lcore_min, lcore_max);
return -1;
}
for (lcore = lcore_min; lcore <= lcore_max; lcore++) {
spdk_cpuset_set_cpu(set, lcore, true);
}
lcore_min = UINT32_MAX;
} else {
goto invalid_character;
}
ptr = end + 1;
} while (*end != ']');
return 0;
invalid_character:
if (*end == '\0') {
SPDK_ERRLOG("Unexpected end of core list '%s'\n", mask);
} else {
SPDK_ERRLOG("Parsing of core list '%s' failed on character '%c'\n", mask, *end);
}
return -1;
}
static int
parse_mask(const char *mask, struct spdk_cpuset *set, size_t len)
{
int i, j;
char c;
int val;
uint32_t lcore = 0;
if (mask[0] == '0' && (mask[1] == 'x' || mask[1] == 'X')) {
mask += 2;
len -= 2;
}
spdk_cpuset_zero(set);
for (i = len - 1; i >= 0; i--) {
c = mask[i];
val = hex_value(c);
if (val < 0) {
/* Invalid character */
SPDK_ERRLOG("Invalid character in core mask '%s' (%c)\n", mask, c);
return -1;
}
for (j = 0; j < 4 && lcore < sizeof(set->cpus); j++, lcore++) {
if ((1 << j) & val) {
spdk_cpuset_set_cpu(set, lcore, true);
}
}
}
return 0;
}
int
spdk_cpuset_parse(struct spdk_cpuset *set, const char *mask)
{
int ret;
size_t len;
if (mask == NULL || set == NULL) {
return -1;
}
while (isblank(*mask)) {
mask++;
}
len = strlen(mask);
while (len > 0 && isblank(mask[len - 1])) {
len--;
}
if (len == 0) {
return -1;
}
if (mask[0] == '[') {
ret = parse_list(mask, set);
} else {
ret = parse_mask(mask, set, len);
}
return ret;
}