Index: user/jeff/numa/usr.bin/numactl/numactl.c =================================================================== --- user/jeff/numa/usr.bin/numactl/numactl.c (revision 327713) +++ user/jeff/numa/usr.bin/numactl/numactl.c (revision 327714) @@ -1,285 +1,315 @@ /* * Copyright (c) 2015 Adrian Chadd * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static struct option longopts[] = { { "tid", required_argument, NULL, 't' }, { "pid", required_argument, NULL, 'p' }, { "memdomain", required_argument, NULL, 'm' }, { "cpudomain", required_argument, NULL, 'c' }, { "mempolicy", required_argument, NULL, 'l' }, { "set", no_argument, NULL, 's' }, { "get", no_argument, NULL, 'g' }, { NULL, 0, NULL, 0 } }; static const char * -policy_to_str(vm_domain_policy_type_t vt) +policy_to_str(int policy) { - switch (vt) { - case VM_POLICY_NONE: - return ("none"); - case VM_POLICY_ROUND_ROBIN: - return ("rr"); - case VM_POLICY_FIXED_DOMAIN: - return ("fixed-domain"); - case VM_POLICY_FIXED_DOMAIN_ROUND_ROBIN: - return ("fixed-domain-rr"); - case VM_POLICY_FIRST_TOUCH: + switch (policy) { + case DOMAINSET_POLICY_INVALID: + return ("invalid"); + case DOMAINSET_POLICY_ROUNDROBIN: + return ("round-robin"); + case DOMAINSET_POLICY_FIRSTTOUCH: return ("first-touch"); - case VM_POLICY_FIRST_TOUCH_ROUND_ROBIN: - return ("first-touch-rr"); + case DOMAINSET_POLICY_PREFER: + return ("prefer"); default: return ("unknown"); } } +static void +domain_print(domainset_t *mask) +{ + int once; + int bit; + + for (once = 0, bit = 0; bit < DOMAINSET_SETSIZE; bit++) { + if (DOMAINSET_ISSET(bit, mask)) { + if (once == 0) { + printf("%d", bit); + once = 1; + } else + printf(", %d", bit); + } + } + printf("\n"); +} + static int -parse_policy(struct vm_domain_policy_entry *vd, const char *str) +parse_policy(int *policy, const char *str) { if (strcmp(str, "rr") == 0) { - vd->policy = VM_POLICY_ROUND_ROBIN; - vd->domain = -1; + *policy = DOMAINSET_POLICY_ROUNDROBIN; return (0); } if (strcmp(str, "first-touch-rr") == 0) { - vd->policy = VM_POLICY_FIRST_TOUCH_ROUND_ROBIN; - vd->domain = -1; + *policy = DOMAINSET_POLICY_FIRSTTOUCH; return (0); } if (strcmp(str, "first-touch") == 0) { - vd->policy = VM_POLICY_FIRST_TOUCH; - vd->domain = -1; + *policy = DOMAINSET_POLICY_FIRSTTOUCH; return (0); } if (strcmp(str, "fixed-domain") == 0) { - vd->policy = VM_POLICY_FIXED_DOMAIN; - vd->domain = 0; + *policy = DOMAINSET_POLICY_PREFER; return (0); } if (strcmp(str, "fixed-domain-rr") == 0) { - vd->policy = VM_POLICY_FIXED_DOMAIN_ROUND_ROBIN; - vd->domain = 0; + *policy = DOMAINSET_POLICY_PREFER; return (0); } return (-1); } static void usage(void) { printf("usage: numactl --get [--tid/-t ] [--pid/-p ]\n"); printf(" numactl --set [--tid=] [--pid/-p]\n"); printf(" [--mempolicy/-l ] [--memdomain/" "-m ]\n"); printf(" [--cpudomain/-c ]\n"); printf(" numactl [--mempolicy/-l ] [--memdomain/-m " "]\n"); printf(" [--cpudomain/-c ] ...\n"); exit(EX_USAGE); } static int set_numa_domain_cpuaffinity(int cpu_domain, cpuwhich_t which, id_t id) { cpuset_t set; int error; error = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_DOMAIN, cpu_domain, sizeof(set), &set); if (error != 0) err(1, "cpuset_getaffinity"); error = cpuset_setaffinity(CPU_LEVEL_WHICH, which, id, sizeof(set), &set); if (error != 0) err(1, "cpuset_setaffinity"); return (0); } +/* + * Attempt to maintain compatability with old style syscalls. + */ +static int +numa_setaffinity(cpuwhich_t which, id_t id, int policy, int domain) +{ + domainset_t mask; + int p; + + DOMAINSET_ZERO(&mask); + if (policy == DOMAINSET_POLICY_PREFER) + DOMAINSET_SET(domain, &mask); + else if (cpuset_getdomain(CPU_LEVEL_ROOT, CPU_WHICH_PID, -1, + sizeof(mask), &mask, &p) != 0) + err(EXIT_FAILURE, "getdomain"); + return cpuset_setdomain(CPU_LEVEL_WHICH, which, id, sizeof(mask), + &mask, policy); +} + int main(int argc, char *argv[]) { - struct vm_domain_policy_entry vd; lwpid_t tid; pid_t pid; cpuwhich_t which; id_t id; int error; int is_set, is_get; int mem_policy_set; int ch; int cpu_domain; + int policy; + int domain; id = -1; which = -1; is_set = 0; is_get = 0; mem_policy_set = 0; tid = -1; pid = -1; cpu_domain = -1; + domain = -1; + policy = DOMAINSET_POLICY_INVALID; while ((ch = getopt_long(argc, argv, "c:gl:m:p:st:", longopts, NULL)) != -1) { switch (ch) { case 'c': cpu_domain = atoi(optarg); break; case 'g': is_get = 1; break; case 'l': - if (parse_policy(&vd, optarg) != 0) { + if (parse_policy(&policy, optarg) != 0) { fprintf(stderr, "Could not parse policy: '%s'\n", optarg); exit(1); } mem_policy_set = 1; break; case 'm': - if (mem_policy_set == 0) { - fprintf(stderr, - "Error: set policy first before domain\n"); - exit(1); - } - vd.domain = atoi(optarg); + domain = atoi(optarg); break; case 'p': pid = atoi(optarg); break; case 's': is_set = 1; break; case 't': tid = atoi(optarg); break; default: usage(); } } argc -= optind; argv += optind; /* Handle the user wishing to run a command */ if (argc) { /* Ensure that a policy was set */ if (mem_policy_set == 0) { fprintf(stderr, "Error: no policy given\n"); usage(); } /* Set current memory process policy, will be inherited */ - if (numa_setaffinity(CPU_WHICH_PID, -1, &vd) != 0) + if (numa_setaffinity(CPU_WHICH_PID, -1, policy, domain) != 0) err(1, "numa_setaffinity"); /* If a CPU domain policy was given, include that too */ if (cpu_domain != -1) (void) set_numa_domain_cpuaffinity(cpu_domain, CPU_WHICH_PID, -1); errno = 0; execvp(*argv, argv); err(errno == ENOENT ? 127 : 126, "%s", *argv); } /* Figure out which */ if (tid != -1) { which = CPU_WHICH_TID; id = tid; } else if (pid != -1) { which = CPU_WHICH_PID; id = pid; } else { fprintf(stderr, "Error: one of tid or pid must be given\n"); usage(); } /* Sanity checks */ if (is_set && is_get) { fprintf(stderr, "Error: can't set both 'set' and 'get'\n"); usage(); } if (is_set && ! mem_policy_set) { fprintf(stderr, "Error: --set given, but no policy\n"); usage(); } /* If it's get, then get the policy and return */ if (is_get) { - error = numa_getaffinity(which, id, &vd); + domainset_t mask; + + printf("which %d, id %ld\n", which, id); + error = cpuset_getdomain(CPU_LEVEL_WHICH, which, id, + sizeof(mask), &mask, &policy); if (error != 0) - err(1, "numa_getaffinity"); - printf(" Policy: %s; domain: %d\n", - policy_to_str(vd.policy), - vd.domain); + err(1, "cpuset_getdomain"); + printf(" Policy: %s; domain: ", + policy_to_str(policy)); + domain_print(&mask); exit(0); } /* Assume it's set */ /* Syscall */ - error = numa_setaffinity(which, id, &vd); + error = numa_setaffinity(which, id, policy, domain); if (error != 0) err(1, "numa_setaffinity"); /* If a CPU domain policy was given, include that too */ if (cpu_domain != -1) (void) set_numa_domain_cpuaffinity(cpu_domain, which, id); exit(0); }