diff options
Diffstat (limited to 'libblkid/cpuset.c')
-rw-r--r-- | libblkid/cpuset.c | 402 |
1 files changed, 0 insertions, 402 deletions
diff --git a/libblkid/cpuset.c b/libblkid/cpuset.c deleted file mode 100644 index e5b6b9dfe..000000000 --- a/libblkid/cpuset.c +++ /dev/null @@ -1,402 +0,0 @@ -/* - * Terminology: - * - * cpuset - (libc) cpu_set_t data structure represents set of CPUs - * cpumask - string with hex mask (e.g. "0x00000001") - * cpulist - string with CPU ranges (e.g. "0-3,5,7,8") - * - * Based on code from taskset.c and Linux kernel. - * - * This file may be redistributed under the terms of the - * GNU Lesser General Public License. - * - * Copyright (C) 2010 Karel Zak <kzak@redhat.com> - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <sched.h> -#include <errno.h> -#include <string.h> -#include <ctype.h> -#include <sys/syscall.h> - -#include "cpuset.h" -#include "c.h" - -static inline int val_to_char(int v) -{ - if (v >= 0 && v < 10) - return '0' + v; - else if (v >= 10 && v < 16) - return ('a' - 10) + v; - else - return -1; -} - -static inline int char_to_val(int c) -{ - int cl; - - cl = tolower(c); - if (c >= '0' && c <= '9') - return c - '0'; - else if (cl >= 'a' && cl <= 'f') - return cl + (10 - 'a'); - else - return -1; -} - -static const char *nexttoken(const char *q, int sep) -{ - if (q) - q = strchr(q, sep); - if (q) - q++; - return q; -} - -/* - * Number of bits in a CPU bitmask on current system - */ -int get_max_number_of_cpus(void) -{ -#ifdef SYS_sched_getaffinity - int n, cpus = 2048; - size_t setsize; - cpu_set_t *set = cpuset_alloc(cpus, &setsize, NULL); - - if (!set) - return -1; /* error */ - - for (;;) { - CPU_ZERO_S(setsize, set); - - /* the library version does not return size of cpumask_t */ - n = syscall(SYS_sched_getaffinity, 0, setsize, set); - - if (n < 0 && errno == EINVAL && cpus < 1024 * 1024) { - cpuset_free(set); - cpus *= 2; - set = cpuset_alloc(cpus, &setsize, NULL); - if (!set) - return -1; /* error */ - continue; - } - cpuset_free(set); - return n * 8; - } -#endif - return -1; -} - -/* - * Allocates a new set for ncpus and returns size in bytes and size in bits - */ -cpu_set_t *cpuset_alloc(int ncpus, size_t *setsize, size_t *nbits) -{ - cpu_set_t *set = CPU_ALLOC(ncpus); - - if (!set) - return NULL; - if (setsize) - *setsize = CPU_ALLOC_SIZE(ncpus); - if (nbits) - *nbits = cpuset_nbits(CPU_ALLOC_SIZE(ncpus)); - return set; -} - -void cpuset_free(cpu_set_t *set) -{ - CPU_FREE(set); -} - -#if !HAVE_DECL_CPU_ALLOC -/* Please, use CPU_COUNT_S() macro. This is fallback */ -int __cpuset_count_s(size_t setsize, const cpu_set_t *set) -{ - int s = 0; - const __cpu_mask *p = set->__bits; - const __cpu_mask *end = &set->__bits[setsize / sizeof (__cpu_mask)]; - - while (p < end) { - __cpu_mask l = *p++; - - if (l == 0) - continue; -# if LONG_BIT > 32 - l = (l & 0x5555555555555555ul) + ((l >> 1) & 0x5555555555555555ul); - l = (l & 0x3333333333333333ul) + ((l >> 2) & 0x3333333333333333ul); - l = (l & 0x0f0f0f0f0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0f0f0f0f0ful); - l = (l & 0x00ff00ff00ff00fful) + ((l >> 8) & 0x00ff00ff00ff00fful); - l = (l & 0x0000ffff0000fffful) + ((l >> 16) & 0x0000ffff0000fffful); - l = (l & 0x00000000fffffffful) + ((l >> 32) & 0x00000000fffffffful); -# else - l = (l & 0x55555555ul) + ((l >> 1) & 0x55555555ul); - l = (l & 0x33333333ul) + ((l >> 2) & 0x33333333ul); - l = (l & 0x0f0f0f0ful) + ((l >> 4) & 0x0f0f0f0ful); - l = (l & 0x00ff00fful) + ((l >> 8) & 0x00ff00fful); - l = (l & 0x0000fffful) + ((l >> 16) & 0x0000fffful); -# endif - s += l; - } - return s; -} -#endif - -/* - * Returns human readable representation of the cpuset. The output format is - * a list of CPUs with ranges (for example, "0,1,3-9"). - */ -char *cpulist_create(char *str, size_t len, - cpu_set_t *set, size_t setsize) -{ - size_t i; - char *ptr = str; - int entry_made = 0; - size_t max = cpuset_nbits(setsize); - - for (i = 0; i < max; i++) { - if (CPU_ISSET_S(i, setsize, set)) { - int rlen; - size_t j, run = 0; - entry_made = 1; - for (j = i + 1; j < max; j++) { - if (CPU_ISSET_S(j, setsize, set)) - run++; - else - break; - } - if (!run) - rlen = snprintf(ptr, len, "%zd,", i); - else if (run == 1) { - rlen = snprintf(ptr, len, "%zd,%zd,", i, i + 1); - i++; - } else { - rlen = snprintf(ptr, len, "%zd-%zd,", i, i + run); - i += run; - } - if (rlen < 0 || (size_t) rlen + 1 > len) - return NULL; - ptr += rlen; - if (rlen > 0 && len > (size_t) rlen) - len -= rlen; - else - len = 0; - } - } - ptr -= entry_made; - *ptr = '\0'; - - return str; -} - -/* - * Returns string with CPU mask. - */ -char *cpumask_create(char *str, size_t len, - cpu_set_t *set, size_t setsize) -{ - char *ptr = str; - char *ret = NULL; - int cpu; - - for (cpu = cpuset_nbits(setsize) - 4; cpu >= 0; cpu -= 4) { - char val = 0; - - if (len == (size_t) (ptr - str)) - break; - - if (CPU_ISSET_S(cpu, setsize, set)) - val |= 1; - if (CPU_ISSET_S(cpu + 1, setsize, set)) - val |= 2; - if (CPU_ISSET_S(cpu + 2, setsize, set)) - val |= 4; - if (CPU_ISSET_S(cpu + 3, setsize, set)) - val |= 8; - - if (!ret && val) - ret = ptr; - *ptr++ = val_to_char(val); - } - *ptr = '\0'; - return ret ? ret : ptr - 1; -} - -/* - * Parses string with CPUs mask. - */ -int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize) -{ - int len = strlen(str); - const char *ptr = str + len - 1; - int cpu = 0; - - /* skip 0x, it's all hex anyway */ - if (len > 1 && !memcmp(str, "0x", 2L)) - str += 2; - - CPU_ZERO_S(setsize, set); - - while (ptr >= str) { - char val; - - /* cpu masks in /sys uses comma as a separator */ - if (*ptr == ',') - ptr--; - - val = char_to_val(*ptr); - if (val == (char) -1) - return -1; - if (val & 1) - CPU_SET_S(cpu, setsize, set); - if (val & 2) - CPU_SET_S(cpu + 1, setsize, set); - if (val & 4) - CPU_SET_S(cpu + 2, setsize, set); - if (val & 8) - CPU_SET_S(cpu + 3, setsize, set); - len--; - ptr--; - cpu += 4; - } - - return 0; -} - -/* - * Parses string with list of CPU ranges. - * Returns 0 on success. - * Returns 1 on error. - * Returns 2 if fail is set and a cpu number passed in the list doesn't fit - * into the cpu_set. If fail is not set cpu numbers that do not fit are - * ignored and 0 is returned instead. - */ -int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail) -{ - size_t max = cpuset_nbits(setsize); - const char *p, *q; - int r = 0; - - q = str; - CPU_ZERO_S(setsize, set); - - while (p = q, q = nexttoken(q, ','), p) { - unsigned int a; /* beginning of range */ - unsigned int b; /* end of range */ - unsigned int s; /* stride */ - const char *c1, *c2; - char c; - - if ((r = sscanf(p, "%u%c", &a, &c)) < 1) - return 1; - b = a; - s = 1; - - c1 = nexttoken(p, '-'); - c2 = nexttoken(p, ','); - if (c1 != NULL && (c2 == NULL || c1 < c2)) { - if ((r = sscanf(c1, "%u%c", &b, &c)) < 1) - return 1; - c1 = nexttoken(c1, ':'); - if (c1 != NULL && (c2 == NULL || c1 < c2)) { - if ((r = sscanf(c1, "%u%c", &s, &c)) < 1) - return 1; - if (s == 0) - return 1; - } - } - - if (!(a <= b)) - return 1; - while (a <= b) { - if (fail && (a >= max)) - return 2; - CPU_SET_S(a, setsize, set); - a += s; - } - } - - if (r == 2) - return 1; - return 0; -} - -#ifdef TEST_PROGRAM - -#include <getopt.h> - -int main(int argc, char *argv[]) -{ - cpu_set_t *set; - size_t setsize, buflen, nbits; - char *buf, *mask = NULL, *range = NULL; - int ncpus = 2048, rc, c; - - static const struct option longopts[] = { - { "ncpus", 1, 0, 'n' }, - { "mask", 1, 0, 'm' }, - { "range", 1, 0, 'r' }, - { NULL, 0, 0, 0 } - }; - - while ((c = getopt_long(argc, argv, "n:m:r:", longopts, NULL)) != -1) { - switch(c) { - case 'n': - ncpus = atoi(optarg); - break; - case 'm': - mask = strdup(optarg); - break; - case 'r': - range = strdup(optarg); - break; - default: - goto usage_err; - } - } - - if (!mask && !range) - goto usage_err; - - set = cpuset_alloc(ncpus, &setsize, &nbits); - if (!set) - err(EXIT_FAILURE, "failed to allocate cpu set"); - - /* - fprintf(stderr, "ncpus: %d, cpuset bits: %zd, cpuset bytes: %zd\n", - ncpus, nbits, setsize); - */ - - buflen = 7 * nbits; - buf = malloc(buflen); - if (!buf) - err(EXIT_FAILURE, "failed to allocate cpu set buffer"); - - if (mask) - rc = cpumask_parse(mask, set, setsize); - else - rc = cpulist_parse(range, set, setsize, 0); - - if (rc) - errx(EXIT_FAILURE, "failed to parse string: %s", mask ? : range); - - printf("%-15s = %15s ", mask ? : range, - cpumask_create(buf, buflen, set, setsize)); - printf("[%s]\n", cpulist_create(buf, buflen, set, setsize)); - - free(buf); - free(range); - cpuset_free(set); - - return EXIT_SUCCESS; - -usage_err: - fprintf(stderr, - "usage: %s [--ncpus <num>] --mask <mask> | --range <list>", - program_invocation_short_name); - exit(EXIT_FAILURE); -} -#endif |