diff options
author | Karel Zak | 2010-05-24 12:44:39 +0200 |
---|---|---|
committer | Karel Zak | 2010-06-01 11:04:44 +0200 |
commit | efcb71f8ff36a5d9f56f04cc8b7cef82ecd98831 (patch) | |
tree | 902c1c3da5b3109f20bb34c5955510f23907ff70 /lib/cpuset.c | |
parent | mount: fix coding style (diff) | |
download | kernel-qcow2-util-linux-efcb71f8ff36a5d9f56f04cc8b7cef82ecd98831.tar.gz kernel-qcow2-util-linux-efcb71f8ff36a5d9f56f04cc8b7cef82ecd98831.tar.xz kernel-qcow2-util-linux-efcb71f8ff36a5d9f56f04cc8b7cef82ecd98831.zip |
taskset: move bitmap routines to lib/cpuset.c
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib/cpuset.c')
-rw-r--r-- | lib/cpuset.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/lib/cpuset.c b/lib/cpuset.c new file mode 100644 index 000000000..abdd40901 --- /dev/null +++ b/lib/cpuset.c @@ -0,0 +1,241 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <getopt.h> +#include <sched.h> +#include <errno.h> +#include <string.h> +#include <ctype.h> +#include <sys/syscall.h> + +#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; +} |