From: Karel Zak Date: Mon, 24 May 2010 10:44:39 +0000 (+0200) Subject: taskset: move bitmap routines to lib/cpuset.c X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=efcb71f8ff36a5d9f56f04cc8b7cef82ecd98831;p=util-linux taskset: move bitmap routines to lib/cpuset.c Signed-off-by: Karel Zak --- diff --git a/include/cpuset.h b/include/cpuset.h new file mode 100644 index 00000000..373fd9ba --- /dev/null +++ b/include/cpuset.h @@ -0,0 +1,23 @@ +#ifndef UTIL_LINUX_CPUSET_H +#define UTIL_LINUX_CPUSET_H + +struct bitmask { + unsigned int size; + unsigned long *maskp; +}; + + +#define howmany(x,y) (((x)+((y)-1))/(y)) +#define bitsperlong (8 * sizeof(unsigned long)) +#define longsperbits(n) howmany(n, bitsperlong) +#define bytesperbits(x) ((x+7)/8) + +extern unsigned int bitmask_nbytes(struct bitmask *bmp); +extern struct bitmask *bitmask_alloc(unsigned int n); + +extern char *cpuset_to_cstr(struct bitmask *mask, char *str); +extern char *cpuset_to_str(struct bitmask *mask, char *str); +extern int str_to_cpuset(struct bitmask *mask, const char* str); +extern int cstr_to_cpuset(struct bitmask *mask, const char* str); + +#endif /* UTIL_LINUX_CPUSET_H */ diff --git a/lib/cpuset.c b/lib/cpuset.c new file mode 100644 index 00000000..abdd4090 --- /dev/null +++ b/lib/cpuset.c @@ -0,0 +1,241 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cpuset.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; +} + +/* + * The following bitmask declarations, bitmask_*() routines, and associated + * _setbit() and _getbit() routines are: + * Copyright (c) 2004 Silicon Graphics, Inc. (SGI) All rights reserved. + * SGI publishes it under the terms of the GNU General Public License, v2, + * as published by the Free Software Foundation. + */ + +static unsigned int _getbit(const struct bitmask *bmp, unsigned int n) +{ + if (n < bmp->size) + return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1; + else + return 0; +} + +static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v) +{ + if (n < bmp->size) { + if (v) + bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong); + else + bmp->maskp[n/bitsperlong] &= ~(1UL << (n % bitsperlong)); + } +} + +static int bitmask_isbitset(const struct bitmask *bmp, unsigned int i) +{ + return _getbit(bmp, i); +} + +struct bitmask *bitmask_clearall(struct bitmask *bmp) +{ + unsigned int i; + for (i = 0; i < bmp->size; i++) + _setbit(bmp, i, 0); + return bmp; +} + +struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i) +{ + _setbit(bmp, i, 1); + return bmp; +} + +unsigned int bitmask_nbytes(struct bitmask *bmp) +{ + return longsperbits(bmp->size) * sizeof(unsigned long); +} + + +struct bitmask *bitmask_alloc(unsigned int n) +{ + struct bitmask *bmp; + + bmp = malloc(sizeof(*bmp)); + if (!bmp) + return 0; + bmp->size = n; + bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long)); + if (!bmp->maskp) { + free(bmp); + return 0; + } + return bmp; +} + +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; +} + +char *cpuset_to_cstr(struct bitmask *mask, char *str) +{ + int i; + char *ptr = str; + int entry_made = 0; + + for (i = 0; i < mask->size; i++) { + if (bitmask_isbitset(mask, i)) { + int j; + int run = 0; + entry_made = 1; + for (j = i + 1; j < mask->size; j++) { + if (bitmask_isbitset(mask, j)) + run++; + else + break; + } + if (!run) + sprintf(ptr, "%d,", i); + else if (run == 1) { + sprintf(ptr, "%d,%d,", i, i + 1); + i++; + } else { + sprintf(ptr, "%d-%d,", i, i + run); + i += run; + } + while (*ptr != 0) + ptr++; + } + } + ptr -= entry_made; + *ptr = 0; + + return str; +} + +char *cpuset_to_str(struct bitmask *mask, char *str) +{ + int base; + char *ptr = str; + char *ret = 0; + + for (base = mask->size - 4; base >= 0; base -= 4) { + char val = 0; + if (bitmask_isbitset(mask, base)) + val |= 1; + if (bitmask_isbitset(mask, base + 1)) + val |= 2; + if (bitmask_isbitset(mask, base + 2)) + val |= 4; + if (bitmask_isbitset(mask, base + 3)) + val |= 8; + if (!ret && val) + ret = ptr; + *ptr++ = val_to_char(val); + } + *ptr = 0; + return ret ? ret : ptr - 1; +} + +int str_to_cpuset(struct bitmask *mask, const char* str) +{ + int len = strlen(str); + const char *ptr = str + len - 1; + int base = 0; + + /* skip 0x, it's all hex anyway */ + if (len > 1 && !memcmp(str, "0x", 2L)) + str += 2; + + bitmask_clearall(mask); + while (ptr >= str) { + char val = char_to_val(*ptr); + if (val == (char) -1) + return -1; + if (val & 1) + bitmask_setbit(mask, base); + if (val & 2) + bitmask_setbit(mask, base + 1); + if (val & 4) + bitmask_setbit(mask, base + 2); + if (val & 8) + bitmask_setbit(mask, base + 3); + len--; + ptr--; + base += 4; + } + + return 0; +} + +int cstr_to_cpuset(struct bitmask *mask, const char* str) +{ + const char *p, *q; + q = str; + bitmask_clearall(mask); + + 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; + + if (sscanf(p, "%u", &a) < 1) + return 1; + b = a; + s = 1; + + c1 = nexttoken(p, '-'); + c2 = nexttoken(p, ','); + if (c1 != NULL && (c2 == NULL || c1 < c2)) { + if (sscanf(c1, "%u", &b) < 1) + return 1; + c1 = nexttoken(c1, ':'); + if (c1 != NULL && (c2 == NULL || c1 < c2)) + if (sscanf(c1, "%u", &s) < 1) { + return 1; + } + } + + if (!(a <= b)) + return 1; + while (a <= b) { + bitmask_setbit(mask, a); + a += s; + } + } + + return 0; +} diff --git a/schedutils/Makefile.am b/schedutils/Makefile.am index 88439f2b..13d45c85 100644 --- a/schedutils/Makefile.am +++ b/schedutils/Makefile.am @@ -14,6 +14,7 @@ endif if HAVE_SCHED_GETAFFINITY usrbin_exec_PROGRAMS += taskset +taskset_SOURCES = taskset.c $(top_srcdir)/lib/cpuset.c dist_man_MANS += taskset.1 endif diff --git a/schedutils/taskset.c b/schedutils/taskset.c index 7abb9cbb..ed63a236 100644 --- a/schedutils/taskset.c +++ b/schedutils/taskset.c @@ -36,10 +36,7 @@ #include #include -struct bitmask { - unsigned int size; - unsigned long *maskp; -}; +#include "cpuset.h" static void show_usage(const char *cmd) { @@ -67,239 +64,6 @@ static void show_usage(const char *cmd) fprintf(stderr, " e.g. 0-31:2 is equivalent to mask 0x55555555\n\n"); } -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; -} - -/* - * The following bitmask declarations, bitmask_*() routines, and associated - * _setbit() and _getbit() routines are: - * Copyright (c) 2004 Silicon Graphics, Inc. (SGI) All rights reserved. - * SGI publishes it under the terms of the GNU General Public License, v2, - * as published by the Free Software Foundation. - */ -#define howmany(x,y) (((x)+((y)-1))/(y)) -#define bitsperlong (8 * sizeof(unsigned long)) -#define longsperbits(n) howmany(n, bitsperlong) -#define bytesperbits(x) ((x+7)/8) - -static unsigned int _getbit(const struct bitmask *bmp, unsigned int n) -{ - if (n < bmp->size) - return (bmp->maskp[n/bitsperlong] >> (n % bitsperlong)) & 1; - else - return 0; -} - -static void _setbit(struct bitmask *bmp, unsigned int n, unsigned int v) -{ - if (n < bmp->size) { - if (v) - bmp->maskp[n/bitsperlong] |= 1UL << (n % bitsperlong); - else - bmp->maskp[n/bitsperlong] &= ~(1UL << (n % bitsperlong)); - } -} - -int bitmask_isbitset(const struct bitmask *bmp, unsigned int i) -{ - return _getbit(bmp, i); -} - -struct bitmask *bitmask_clearall(struct bitmask *bmp) -{ - unsigned int i; - for (i = 0; i < bmp->size; i++) - _setbit(bmp, i, 0); - return bmp; -} - -struct bitmask *bitmask_setbit(struct bitmask *bmp, unsigned int i) -{ - _setbit(bmp, i, 1); - return bmp; -} - -unsigned int bitmask_nbytes(struct bitmask *bmp) -{ - return longsperbits(bmp->size) * sizeof(unsigned long); -} - -static char * cpuset_to_str(struct bitmask *mask, char *str) -{ - int base; - char *ptr = str; - char *ret = 0; - - for (base = mask->size - 4; base >= 0; base -= 4) { - char val = 0; - if (bitmask_isbitset(mask, base)) - val |= 1; - if (bitmask_isbitset(mask, base + 1)) - val |= 2; - if (bitmask_isbitset(mask, base + 2)) - val |= 4; - if (bitmask_isbitset(mask, base + 3)) - val |= 8; - if (!ret && val) - ret = ptr; - *ptr++ = val_to_char(val); - } - *ptr = 0; - return ret ? ret : ptr - 1; -} - -struct bitmask *bitmask_alloc(unsigned int n) -{ - struct bitmask *bmp; - - bmp = malloc(sizeof(*bmp)); - if (!bmp) - return 0; - bmp->size = n; - bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long)); - if (!bmp->maskp) { - free(bmp); - return 0; - } - return bmp; -} - -static char * cpuset_to_cstr(struct bitmask *mask, char *str) -{ - int i; - char *ptr = str; - int entry_made = 0; - - for (i = 0; i < mask->size; i++) { - if (bitmask_isbitset(mask, i)) { - int j; - int run = 0; - entry_made = 1; - for (j = i + 1; j < mask->size; j++) { - if (bitmask_isbitset(mask, j)) - run++; - else - break; - } - if (!run) - sprintf(ptr, "%d,", i); - else if (run == 1) { - sprintf(ptr, "%d,%d,", i, i + 1); - i++; - } else { - sprintf(ptr, "%d-%d,", i, i + run); - i += run; - } - while (*ptr != 0) - ptr++; - } - } - ptr -= entry_made; - *ptr = 0; - - return str; -} - -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 int str_to_cpuset(struct bitmask *mask, const char* str) -{ - int len = strlen(str); - const char *ptr = str + len - 1; - int base = 0; - - /* skip 0x, it's all hex anyway */ - if (len > 1 && !memcmp(str, "0x", 2L)) - str += 2; - - bitmask_clearall(mask); - while (ptr >= str) { - char val = char_to_val(*ptr); - if (val == (char) -1) - return -1; - if (val & 1) - bitmask_setbit(mask, base); - if (val & 2) - bitmask_setbit(mask, base + 1); - if (val & 4) - bitmask_setbit(mask, base + 2); - if (val & 8) - bitmask_setbit(mask, base + 3); - len--; - ptr--; - base += 4; - } - - return 0; -} - -static const char *nexttoken(const char *q, int sep) -{ - if (q) - q = strchr(q, sep); - if (q) - q++; - return q; -} - -static int cstr_to_cpuset(struct bitmask *mask, const char* str) -{ - const char *p, *q; - q = str; - bitmask_clearall(mask); - - 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; - - if (sscanf(p, "%u", &a) < 1) - return 1; - b = a; - s = 1; - - c1 = nexttoken(p, '-'); - c2 = nexttoken(p, ','); - if (c1 != NULL && (c2 == NULL || c1 < c2)) { - if (sscanf(c1, "%u", &b) < 1) - return 1; - c1 = nexttoken(c1, ':'); - if (c1 != NULL && (c2 == NULL || c1 < c2)) - if (sscanf(c1, "%u", &s) < 1) { - return 1; - } - } - - if (!(a <= b)) - return 1; - while (a <= b) { - bitmask_setbit(mask, a); - a += s; - } - } - - return 0; -} - /* * Number of bits in a CPU bitmask on current system */