summaryrefslogtreecommitdiff
path: root/usr.bin/cpuset
diff options
context:
space:
mode:
authorJeff Roberson <jeff@FreeBSD.org>2018-01-12 22:48:23 +0000
committerJeff Roberson <jeff@FreeBSD.org>2018-01-12 22:48:23 +0000
commit3f289c3fcf39b200550e2702068014cdd801d4da (patch)
tree9105f2f717d4e6d5f5dc06d92b4b158e3c831d9e /usr.bin/cpuset
parentfe8be58826d91f5b80b50bac161b727bd4ea9846 (diff)
downloadsrc-test-3f289c3fcf39b200550e2702068014cdd801d4da.tar.gz
src-test-3f289c3fcf39b200550e2702068014cdd801d4da.zip
Implement 'domainset', a cpuset based NUMA policy mechanism. This allows
userspace to control NUMA policy administratively and programmatically. Implement domainset based iterators in the page layer. Remove the now legacy numa_* syscalls. Cleanup some header polution created by having seq.h in proc.h. Reviewed by: markj, kib Discussed with: alc Tested by: pho Sponsored by: Netflix, Dell/EMC Isilon Differential Revision: https://reviews.freebsd.org/D13403
Notes
Notes: svn path=/head/; revision=327895
Diffstat (limited to 'usr.bin/cpuset')
-rw-r--r--usr.bin/cpuset/cpuset.c153
1 files changed, 127 insertions, 26 deletions
diff --git a/usr.bin/cpuset/cpuset.c b/usr.bin/cpuset/cpuset.c
index 160d76e024067..0f1dcfe2ccc46 100644
--- a/usr.bin/cpuset/cpuset.c
+++ b/usr.bin/cpuset/cpuset.c
@@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/cpuset.h>
+#include <sys/domainset.h>
#include <ctype.h>
#include <err.h>
@@ -55,6 +56,7 @@ static int gflag;
static int iflag;
static int jflag;
static int lflag;
+static int nflag;
static int pflag;
static int rflag;
static int sflag;
@@ -66,30 +68,40 @@ static cpuwhich_t which;
static void usage(void);
-static void printset(cpuset_t *mask);
+struct numa_policy {
+ const char *name;
+ int policy;
+};
+
+static struct numa_policy policies[] = {
+ { "round-robin", DOMAINSET_POLICY_ROUNDROBIN },
+ { "rr", DOMAINSET_POLICY_ROUNDROBIN },
+ { "first-touch", DOMAINSET_POLICY_FIRSTTOUCH },
+ { "ft", DOMAINSET_POLICY_FIRSTTOUCH },
+ { "prefer", DOMAINSET_POLICY_PREFER },
+ { NULL, DOMAINSET_POLICY_INVALID }
+};
+
+BITSET_DEFINE(bitset, 1);
+static void printset(struct bitset *mask, int size);
static void
-parselist(char *list, cpuset_t *mask)
+parselist(char *list, struct bitset *mask, int size)
{
enum { NONE, NUM, DASH } state;
int lastnum;
int curnum;
char *l;
- if (strcasecmp(list, "all") == 0) {
- if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1,
- sizeof(*mask), mask) != 0)
- err(EXIT_FAILURE, "getaffinity");
- return;
- }
state = NONE;
curnum = lastnum = 0;
for (l = list; *l != '\0';) {
if (isdigit(*l)) {
curnum = atoi(l);
- if (curnum > CPU_SETSIZE)
+ if (curnum > size)
errx(EXIT_FAILURE,
- "Only %d cpus supported", CPU_SETSIZE);
+ "List entry %d exceeds maximum of %d",
+ curnum, size);
while (isdigit(*l))
l++;
switch (state) {
@@ -99,7 +111,7 @@ parselist(char *list, cpuset_t *mask)
break;
case DASH:
for (; lastnum <= curnum; lastnum++)
- CPU_SET(lastnum, mask);
+ BIT_SET(size, lastnum, mask);
state = NONE;
break;
case NUM:
@@ -114,7 +126,7 @@ parselist(char *list, cpuset_t *mask)
case NONE:
break;
case NUM:
- CPU_SET(curnum, mask);
+ BIT_SET(size, curnum, mask);
state = NONE;
break;
case DASH:
@@ -136,29 +148,86 @@ parselist(char *list, cpuset_t *mask)
case NONE:
break;
case NUM:
- CPU_SET(curnum, mask);
+ BIT_SET(size, curnum, mask);
break;
case DASH:
goto parserr;
}
return;
parserr:
- errx(EXIT_FAILURE, "Malformed cpu-list %s", list);
+ errx(EXIT_FAILURE, "Malformed list %s", list);
+}
+
+static void
+parsecpulist(char *list, cpuset_t *mask)
+{
+
+ if (strcasecmp(list, "all") == 0) {
+ if (cpuset_getaffinity(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1,
+ sizeof(*mask), mask) != 0)
+ err(EXIT_FAILURE, "getaffinity");
+ return;
+ }
+ parselist(list, (struct bitset *)mask, CPU_SETSIZE);
}
+/*
+ * permissively parse policy:domain list
+ * allow:
+ * round-robin:0-4 explicit
+ * round-robin:all explicit root domains
+ * 0-4 implicit root policy
+ * round-robin implicit root domains
+ * all explicit root domains and implicit policy
+ */
static void
-printset(cpuset_t *mask)
+parsedomainlist(char *list, domainset_t *mask, int *policyp)
+{
+ domainset_t rootmask;
+ struct numa_policy *policy;
+ char *l;
+ int p;
+
+ /*
+ * Use the rootset's policy as the default for unspecified policies.
+ */
+ if (cpuset_getdomain(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1,
+ sizeof(rootmask), &rootmask, &p) != 0)
+ err(EXIT_FAILURE, "getdomain");
+
+ l = list;
+ for (policy = &policies[0]; policy->name != NULL; policy++) {
+ if (strncasecmp(l, policy->name, strlen(policy->name)) == 0) {
+ p = policy->policy;
+ l += strlen(policy->name);
+ if (*l != ':' && *l != '\0')
+ errx(EXIT_FAILURE, "Malformed list %s", list);
+ if (*l == ':')
+ l++;
+ break;
+ }
+ }
+ *policyp = p;
+ if (strcasecmp(l, "all") == 0 || *l == '\0') {
+ DOMAINSET_COPY(&rootmask, mask);
+ return;
+ }
+ parselist(l, (struct bitset *)mask, DOMAINSET_SETSIZE);
+}
+
+static void
+printset(struct bitset *mask, int size)
{
int once;
- int cpu;
+ int bit;
- for (once = 0, cpu = 0; cpu < CPU_SETSIZE; cpu++) {
- if (CPU_ISSET(cpu, mask)) {
+ for (once = 0, bit = 0; bit < size; bit++) {
+ if (BIT_ISSET(size, bit, mask)) {
if (once == 0) {
- printf("%d", cpu);
+ printf("%d", bit);
once = 1;
} else
- printf(", %d", cpu);
+ printf(", %d", bit);
}
}
printf("\n");
@@ -167,17 +236,30 @@ printset(cpuset_t *mask)
static const char *whichnames[] = { NULL, "tid", "pid", "cpuset", "irq", "jail",
"domain" };
static const char *levelnames[] = { NULL, " root", " cpuset", "" };
+static const char *policynames[] = { "invalid", "round-robin", "first-touch",
+ "prefer" };
static void
printaffinity(void)
{
+ domainset_t domain;
cpuset_t mask;
+ int policy;
if (cpuset_getaffinity(level, which, id, sizeof(mask), &mask) != 0)
err(EXIT_FAILURE, "getaffinity");
printf("%s %jd%s mask: ", whichnames[which], (intmax_t)id,
levelnames[level]);
- printset(&mask);
+ printset((struct bitset *)&mask, CPU_SETSIZE);
+ if (dflag)
+ goto out;
+ if (cpuset_getdomain(level, which, id, sizeof(domain), &domain,
+ &policy) != 0)
+ err(EXIT_FAILURE, "getdomain");
+ printf("%s %jd%s domain policy: %s mask: ", whichnames[which],
+ (intmax_t)id, levelnames[level], policynames[policy]);
+ printset((struct bitset *)&domain, DOMAINSET_SETSIZE);
+out:
exit(EXIT_SUCCESS);
}
@@ -200,17 +282,21 @@ printsetid(void)
int
main(int argc, char *argv[])
{
+ domainset_t domains;
cpusetid_t setid;
cpuset_t mask;
+ int policy;
lwpid_t tid;
pid_t pid;
int ch;
CPU_ZERO(&mask);
+ DOMAINSET_ZERO(&domains);
+ policy = DOMAINSET_POLICY_INVALID;
level = CPU_LEVEL_WHICH;
which = CPU_WHICH_PID;
id = pid = tid = setid = -1;
- while ((ch = getopt(argc, argv, "Ccd:gij:l:p:rs:t:x:")) != -1) {
+ while ((ch = getopt(argc, argv, "Ccd:gij:l:n:p:rs:t:x:")) != -1) {
switch (ch) {
case 'C':
Cflag = 1;
@@ -237,7 +323,11 @@ main(int argc, char *argv[])
break;
case 'l':
lflag = 1;
- parselist(optarg, &mask);
+ parsecpulist(optarg, &mask);
+ break;
+ case 'n':
+ nflag = 1;
+ parsedomainlist(optarg, &domains, &policy);
break;
case 'p':
pflag = 1;
@@ -270,7 +360,7 @@ main(int argc, char *argv[])
argc -= optind;
argv += optind;
if (gflag) {
- if (argc || Cflag || lflag)
+ if (argc || Cflag || lflag || nflag)
usage();
/* Only one identity specifier. */
if (dflag + jflag + xflag + sflag + pflag + tflag > 1)
@@ -281,6 +371,7 @@ main(int argc, char *argv[])
printaffinity();
exit(EXIT_SUCCESS);
}
+
if (dflag || iflag || rflag)
usage();
/*
@@ -301,6 +392,11 @@ main(int argc, char *argv[])
-1, sizeof(mask), &mask) != 0)
err(EXIT_FAILURE, "setaffinity");
}
+ if (nflag) {
+ if (cpuset_setdomain(level, CPU_WHICH_PID,
+ -1, sizeof(domains), &domains, policy) != 0)
+ err(EXIT_FAILURE, "setdomain");
+ }
errno = 0;
execvp(*argv, argv);
err(errno == ENOENT ? 127 : 126, "%s", *argv);
@@ -310,9 +406,9 @@ main(int argc, char *argv[])
*/
if (Cflag && (jflag || !pflag || sflag || tflag || xflag))
usage();
- if (!lflag && cflag)
+ if ((!lflag && !nflag) && cflag)
usage();
- if (!lflag && !(Cflag || sflag))
+ if ((!lflag && !nflag) && !(Cflag || sflag))
usage();
/* You can only set a mask on a thread. */
if (tflag && (sflag | pflag | xflag | jflag))
@@ -344,6 +440,11 @@ main(int argc, char *argv[])
&mask) != 0)
err(EXIT_FAILURE, "setaffinity");
}
+ if (nflag) {
+ if (cpuset_setdomain(level, which, id, sizeof(domains),
+ &domains, policy) != 0)
+ err(EXIT_FAILURE, "setdomain");
+ }
exit(EXIT_SUCCESS);
}