2 * Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
30 #include <sys/param.h>
31 #include <sys/cpuset.h>
33 #include <sys/resource.h>
49 static struct option longopts[] = {
50 { "tid", required_argument, NULL, 't' },
51 { "pid", required_argument, NULL, 'p' },
52 { "memdomain", required_argument, NULL, 'm' },
53 { "cpudomain", required_argument, NULL, 'c' },
54 { "mempolicy", required_argument, NULL, 'l' },
55 { "set", no_argument, NULL, 's' },
56 { "get", no_argument, NULL, 'g' },
61 policy_to_str(vm_domain_policy_type_t vt)
67 case VM_POLICY_ROUND_ROBIN:
69 case VM_POLICY_FIXED_DOMAIN:
70 return ("fixed-domain");
71 case VM_POLICY_FIXED_DOMAIN_ROUND_ROBIN:
72 return ("fixed-domain-rr");
73 case VM_POLICY_FIRST_TOUCH:
74 return ("first-touch");
75 case VM_POLICY_FIRST_TOUCH_ROUND_ROBIN:
76 return ("first-touch-rr");
83 parse_policy(struct vm_domain_policy_entry *vd, const char *str)
86 if (strcmp(str, "rr") == 0) {
87 vd->policy = VM_POLICY_ROUND_ROBIN;
92 if (strcmp(str, "first-touch-rr") == 0) {
93 vd->policy = VM_POLICY_FIRST_TOUCH_ROUND_ROBIN;
98 if (strcmp(str, "first-touch") == 0) {
99 vd->policy = VM_POLICY_FIRST_TOUCH;
104 if (strcmp(str, "fixed-domain") == 0) {
105 vd->policy = VM_POLICY_FIXED_DOMAIN;
110 if (strcmp(str, "fixed-domain-rr") == 0) {
111 vd->policy = VM_POLICY_FIXED_DOMAIN_ROUND_ROBIN;
123 printf("usage: numactl --get [--tid/-t <tid>] [--pid/-p <pid>]\n");
124 printf(" numactl --set [--tid=<tid>] [--pid/-p<pid>]\n");
125 printf(" [--mempolicy/-l <policy>] [--memdomain/"
127 printf(" [--cpudomain/-c <domain>]\n");
128 printf(" numactl [--mempolicy/-l <policy>] [--memdomain/-m "
130 printf(" [--cpudomain/-c <domain>] <cmd> ...\n");
136 set_numa_domain_cpuaffinity(int cpu_domain, cpuwhich_t which, id_t id)
141 error = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_DOMAIN,
142 cpu_domain, sizeof(set), &set);
144 err(1, "cpuset_getaffinity");
145 error = cpuset_setaffinity(CPU_LEVEL_WHICH, which, id, sizeof(set),
148 err(1, "cpuset_setaffinity");
154 main(int argc, char *argv[])
156 struct vm_domain_policy_entry vd;
176 while ((ch = getopt_long(argc, argv, "c:gl:m:p:st:", longopts,
180 cpu_domain = atoi(optarg);
186 if (parse_policy(&vd, optarg) != 0) {
188 "Could not parse policy: '%s'\n", optarg);
194 if (mem_policy_set == 0) {
196 "Error: set policy first before domain\n");
199 vd.domain = atoi(optarg);
217 /* Handle the user wishing to run a command */
219 /* Ensure that a policy was set */
220 if (mem_policy_set == 0) {
221 fprintf(stderr, "Error: no policy given\n");
225 /* Set current memory process policy, will be inherited */
226 if (numa_setaffinity(CPU_WHICH_PID, -1, &vd) != 0)
227 err(1, "numa_setaffinity");
229 /* If a CPU domain policy was given, include that too */
230 if (cpu_domain != -1)
231 (void) set_numa_domain_cpuaffinity(cpu_domain,
236 err(errno == ENOENT ? 127 : 126, "%s", *argv);
239 /* Figure out which */
241 which = CPU_WHICH_TID;
243 } else if (pid != -1) {
244 which = CPU_WHICH_PID;
247 fprintf(stderr, "Error: one of tid or pid must be given\n");
252 if (is_set && is_get) {
253 fprintf(stderr, "Error: can't set both 'set' and 'get'\n");
257 if (is_set && ! mem_policy_set) {
258 fprintf(stderr, "Error: --set given, but no policy\n");
262 /* If it's get, then get the policy and return */
264 error = numa_getaffinity(which, id, &vd);
266 err(1, "numa_getaffinity");
267 printf(" Policy: %s; domain: %d\n",
268 policy_to_str(vd.policy),
273 /* Assume it's set */
276 error = numa_setaffinity(which, id, &vd);
278 err(1, "numa_setaffinity");
280 /* If a CPU domain policy was given, include that too */
281 if (cpu_domain != -1)
282 (void) set_numa_domain_cpuaffinity(cpu_domain, which, id);