Remove bits of the old NUMA.

Remove numactl(1), edit numa(4) to bring it some closer to reality,
provide libc ABI shims for old NUMA syscalls.

Noted and reviewed by:	brooks (previous version)
Sponsored by:	The FreeBSD Foundation
Differential revision:	https://reviews.freebsd.org/D16142
This commit is contained in:
Konstantin Belousov 2018-07-10 22:00:20 +00:00
parent 0d26206d04
commit b3042426d0
11 changed files with 26 additions and 761 deletions

View File

@ -38,6 +38,12 @@
# xargs -n1 | sort | uniq -d;
# done
# 20180710: old numa cleanup
OLD_FILES+=usr/include/sys/numa.h
OLD_FILES+=usr/share/man/man2/numa_getaffinity.2.gz
OLD_FILES+=usr/share/man/man2/numa_setaffinity.2.gz
OLD_FILES+=usr/share/man/man1/numactl.1.gz
OLD_FILES+=usr/bin/numactl
# 20180630: new clang import which bumps version from 6.0.0 to 6.0.1.
OLD_FILES+=usr/lib/clang/6.0.0/include/sanitizer/allocator_interface.h
OLD_FILES+=usr/lib/clang/6.0.0/include/sanitizer/asan_interface.h

View File

@ -258,7 +258,6 @@ MAN+= abort2.2 \
nanosleep.2 \
nfssvc.2 \
ntp_adjtime.2 \
numa_getaffinity.2 \
open.2 \
pathconf.2 \
pdfork.2 \
@ -430,7 +429,6 @@ MLINKS+=mount.2 nmount.2 \
MLINKS+=mq_receive.2 mq_timedreceive.2
MLINKS+=mq_send.2 mq_timedsend.2
MLINKS+=ntp_adjtime.2 ntp_gettime.2
MLINKS+=numa_getaffinity.2 numa_setaffinity.2
MLINKS+=open.2 openat.2
MLINKS+=pathconf.2 fpathconf.2
MLINKS+=pathconf.2 lpathconf.2

View File

@ -54,3 +54,5 @@ __sym_compat(symbol, __compat_enosys ## symbol, version)
__compat_nosys(netbsd_lchown, FBSD_1.0);
__compat_nosys(netbsd_msync, FBSD_1.0);
__compat_nosys(numa_getaffinity, FBSD_1.4);
__compat_nosys(numa_setaffinity, FBSD_1.4);

View File

@ -1,197 +0,0 @@
.\" Copyright (c) 2008 Christian Brueffer
.\" Copyright (c) 2008 Jeffrey Roberson
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd May 7, 2015
.Dt NUMA_GETAFFINITY 2
.Os
.Sh NAME
.Nm numa_getaffinity ,
.Nm numa_setaffinity
.Nd manage NUMA affinity
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
.In sys/param.h
.In sys/numa.h
.Ft int
.Fn numa_getaffinity "cpuwhich_t which" "id_t id" "struct vm_domain_policy_entry *policy"
.Ft int
.Fn numa_setaffinity "cpuwhich_t which" "id_t id" "const struct vm_domain_policy_entry *policy"
.Sh DESCRIPTION
.Fn numa_getaffinity
and
.Fn numa_setaffinity
allow the manipulation of NUMA policies available to processes and threads.
These functions may manipulate NUMA policies that contain many processes
or affect only a single object.
.Pp
Valid values for the
.Fa which
argument are documented in
.Xr cpuset 2 .
These arguments specify which object set are used.
Only
.Dv CPU_WHICH_TID
and
.Dv CPU_WHICH_PID
can be manipulated.
.Pp
The
.Fa policy
entry contains a vm_domain_policy_entry with the following fields:
.Bd -literal
struct vm_domain_policy_entry {
vm_domain_policy_type_t policy; /* VM policy */
int domain; /* VM domain, if applicable */
}
.Ed
.Fa vm_domain_policy_type_t policy
is one these:
.Bl -tag -width VM_POLICY_NONE
.It Dv VM_POLICY_NONE
Reset the domain back to none.
Any parent object NUMA domain policy will apply.
The only valid value for
.Dv domain
is -1.
.It Dv VM_POLICY_ROUND_ROBIN
Select round-robin policy.
Pages will be allocated round-robin from each VM domain in order.
The only valid value for
.Dv domain
is -1.
.It Dv VM_POLICY_FIXED_DOMAIN
Select fixed-domain only policy.
Pages will be allocated from the given
.Dv domain
which must be set to a valid VM domain.
Pages will not be allocated from another domain if
.Dv domain
is out of free pages.
.It Dv VM_POLICY_FIXED_DOMAIN_ROUND_ROBIN
Select fixed-domain only policy.
Pages will be allocated from
.Dv domain
which must be set to a valid VM domain.
If page allocation fails, pages will be round-robin
allocated from another domain if
.Dv domain
is out of free pages.
.It Dv VM_POLICY_FIRST_TOUCH
Select first-touch policy.
Pages will be allocated from the NUMA domain which the thread
is currently scheduled upon.
Pages will not be allocated from another domain if the current domain
is out of free pages.
The only valid value for
.Dv domain
is -1.
.It Dv VM_POLICY_FIRST_TOUCH_ROUND_ROBIN
Select first-touch policy.
Pages will be allocated from the NUMA domain which the thread
is currently scheduled upon.
Pages will be allocated round-robin from another domain if the
current domain is out of free pages.
The only valid value for
.Dv domain
is -1.
.El
.Pp
Note that the VM might assign some pages from other domains.
For example, if an existing page allocation is covered by a superpage
allocation.
.Pp
.Fn numa_getaffinity
retrieves the
NUMA policy from the object specified by
.Fa which
and
.Fa id
and stores it in the space provided by
.Fa policy .
.Pp
.Fn numa_setaffinity
attempts to set the NUMA policy for the object specified by
.Fa which
and
.Fa id
to the policy in
.Fa policy .
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
.Va errno
can contain these error codes:
.Bl -tag -width Er
.It Bq Er EINVAL
The
.Fa level
or
.Fa which
argument was not a valid value.
.It Bq Er EINVAL
The
.Fa policy
argument specified when calling
.Fn numa_setaffinity
did not contain a valid policy.
.It Bq Er EFAULT
The policy pointer passed was invalid.
.It Bq Er ESRCH
The object specified by the
.Fa id
and
.Fa which
arguments could not be found.
.It Bq Er ERANGE
The
.Fa domain
in the given policy
was out of the range of possible VM domains available.
.It Bq Er EPERM
The calling process did not have the credentials required to complete the
operation.
.El
.Sh SEE ALSO
.Xr cpuset 1 ,
.Xr numactl 1 ,
.Xr cpuset 2 ,
.Xr cpuset_getaffinity 2 ,
.Xr cpuset_getid 2 ,
.Xr cpuset_setaffinity 2 ,
.Xr cpuset_setid 2 ,
.Xr pthread_affinity_np 3 ,
.Xr pthread_attr_affinity_np 3 ,
.Xr numa 4
.Sh HISTORY
The
.Nm
family of system calls first appeared in
.Fx 11.0 .
.Sh AUTHORS
.An Adrian Chadd Aq Mt adrian@FreeBSD.org

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd May 10, 2015
.Dd July 10, 2018
.Dt NUMA 4
.Os
.Sh NAME
@ -34,7 +34,6 @@
.Cd options SMP
.Cd options MAXMEMDOM=16
.Pp
.In sys/numa.h
.In sys/cpuset.h
.In sys/bus.h
.Sh DESCRIPTION
@ -51,20 +50,21 @@ that is connected to one of the other processors.
.Pp
.Nm
is enabled when the
.Cd MAXMEMDOM
.Cd NUMA
option is used in a kernel configuration
file and is set to a value greater than 1.
file and the
.Cd MAXMEMDOM
option is set to a value greater than 1.
.Pp
Thread and process
.Nm
policies are controlled with the
.Xr numa_setaffinity 2
.Xr cpuset_getdomain 2
and
.Xr numa_getaffinity 2
.Xr cpuset_setdomain 2
syscalls.
.Pp
The
.Xr numactl 1
.Xr cpuset 1
tool is available for starting processes with a non-default
policy, or to change the policy of an existing thread or process.
.Pp
@ -83,15 +83,6 @@ MIB variables:
.It Va vm.ndomains
The number of VM domains which have been detected.
.Pp
.It Va vm.default_policy
The default VM domain allocation policy.
Defaults to "first-touch-rr".
The valid values are "first-touch", "first-touch-rr",
"rr", where "rr" is a short-hand for "round-robin."
See
.Xr numa_setaffinity 2
for more information about the available policies.
.Pp
.It Va vm.phys_locality
A table indicating the relative cost of each VM domain to each other.
A value of 10 indicates equal cost.
@ -111,36 +102,11 @@ domains are mapped into a contiguous, non-sparse
VM domain space, starting from 0.
Thus, VM domain information (for example, the domain identifier) is not
necessarily the same as is found in the hardware specific information.
.Pp
The
.Nm
allocation policies are implemented as a policy and iterator in
.Pa sys/vm/vm_domain.c
and
.Pa sys/vm/vm_domain.h .
Policy information is available in both struct thread and struct proc.
Processes inherit
.Nm
policy from parent processes and threads inherit
.Nm
policy from parent threads.
Note that threads do not explicitly inherit their
.Nm
policy from processes.
Instead, if no thread policy is set, the system
will fall back to the process policy.
.Pp
For now,
.Nm
domain policies only influence physical page allocation in
.Pa sys/vm/vm_phys.c .
This is useful for userland memory allocation, but not for kernel
and driver memory allocation.
These features will be implemented in future work.
.Sh SEE ALSO
.Xr numactl 1 ,
.Xr numa_getaffinity 2 ,
.Xr numa_setaffinity 2 ,
.Xr cpuset 1 ,
.Xr cpuset_getaffinity 2 ,
.Xr cpuset_setaffinity 2 ,
.Xr bus_get_domain 9
.Sh HISTORY
.Nm
@ -156,13 +122,15 @@ The
.Xr numa_getaffinity 2
and
.Xr numa_setaffinity 2
syscalls first appeared in
.Fx 11.0 .
.Pp
The
syscalls and the
.Xr numactl 1
tool first appeared in
.Fx 11.0 .
.Fx 11.0
and were removed in
.Fx 12.0 .
Current implementation appeared in
.Fx 12.0 .
.Pp
.Sh AUTHORS
This manual page written by
.An Adrian Chadd Aq Mt adrian@FreeBSD.org .

View File

@ -1,43 +0,0 @@
/*
* SPDX-License-Identifier: BSD-3-Clause
*
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>.
* 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.
* 3. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* 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.
*
* $FreeBSD$
*/
#ifndef __SYS_NUMA_H__
#define __SYS_NUMA_H__
#include <sys/_vm_domain.h>
extern int numa_setaffinity(cpuwhich_t which, id_t id,
struct vm_domain_policy_entry *vd);
extern int numa_getaffinity(cpuwhich_t which, id_t id,
struct vm_domain_policy_entry *vd);
#endif /* __SYS_NUMA_H__ */

View File

@ -104,7 +104,6 @@ SUBDIR= alias \
nfsstat \
nice \
nl \
numactl \
nohup \
opieinfo \
opiekey \

View File

@ -1,5 +0,0 @@
# $FreeBSD$
PROG= numactl
.include <bsd.prog.mk>

View File

@ -1,17 +0,0 @@
# $FreeBSD$
# Autogenerated - do NOT edit!
DIRDEPS = \
gnu/lib/csu \
include \
include/xlocale \
lib/${CSU_DIR} \
lib/libc \
lib/libcompiler_rt \
.include <dirdeps.mk>
.if ${DEP_RELDIR} == ${_DEP_RELDIR}
# local dependencies - needed for -jN in clean tree
.endif

View File

@ -1,132 +0,0 @@
.\" Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
.\" 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.
.\"
.\" $FreeBSD$
.\"
.Dd May 9, 2015
.Dt NUMACTL 1
.Os
.Sh NAME
.Nm numactl
.Nd "manage NUMA policy configuration"
.Sh SYNOPSIS
.Nm
.Op Fl l Ar policy
.Op Fl m Ar domain
.Op Fl c Ar domain
.Ar cmd ...
.Nm
.Fl g
.Op Fl p Ar pid
.Op Fl t Ar tid
.Nm
.Fl s
.Op Fl l Ar policy
.Op Fl m Ar domain
.Op Fl c Ar domain
.Op Fl p Ar pid
.Op Fl t Ar tid
.Sh DESCRIPTION
The
.Nm
command can be used to assign NUMA policies to processes/threads,
run commands with a given NUMA policy, and query information
about NUMA policies on running processes.
.Pp
.Nm
requires a target to modify or query.
The target may be specified as a command, process id or a thread id.
Using
.Fl -get
the target's NUMA policy may be queried.
Using
.Fl -set
the target's NUMA policy may be queried.
If no target is specified,
.Nm
operates on itself.
Not all combinations of operations and targets are supported.
For example,
you may not set the id of an existing set or query and launch a command
at the same time.
.Pp
Each process and thread has a NUMA policy.
By default the policy is NONE.
If a thread policy is NONE, then the policy will fall back to the process.
If the process policy is NONE, then the policy will fall back to the
system default.
The policy may be queried by using
.Fl -get.
.Pp
The options are as follows:
.Bl -tag -width ".Fl -cpudomain Ar domain"
.It Fl -cpudomain Ar domain , Fl c Ar domain
Set the given CPU scheduling policy.
Constrain the object (tid, pid, command) to run on CPUs
that belong to the given domain.
.It Fl -get , Fl g
Retrieve the NUMA policy for the given thread or process id.
.It Fl -set , Fl s
Set the NUMA policy for the given thread or process id.
.It Fl -memdomain Ar domain , Fl m Ar domain
Constrain the object (tid, pid, command) to the given
domain.
This is only valid for fixed-domain and fixed-domain-rr.
It must not be set for other policies.
.It Fl -mempolicy Ar policy , Fl l Ar policy
Set the given memory allocation policy.
Valid policies are none, rr, fixed-domain, fixed-domain-rr,
first-touch, and first-touch-rr.
A memdomain argument is required for fixed-domain and
fixed-domain-rr.
.It Fl -pid Ar pid , Fl p Ar pid
Operate on the given pid.
.It Fl -tid Ar tid , Fl t Ar tid
Operate on the given tid.
.El
.Sh EXIT STATUS
.Ex -std
.Sh EXAMPLES
Create a
.Pa /bin/sh
process with memory coming from domain 0, but
CPUs coming from domain 1:
.Dl numactl --mempolicy=fixed-domain --memdomain=0 --cpudomain=1 /bin/sh
.Pp
Query the NUMA policy for the
.Aq sh pid :
.Dl numactl --get --pid=<sh pid>
.Pp
Set the NUMA policy for the given TID to round-robin:
.Dl numactl --set --mempolicy=rr --tid=<tid>
.Sh SEE ALSO
.Xr cpuset 2 ,
.Xr numa 4
.Sh HISTORY
The
.Nm
command first appeared in
.Fx 11.0 .
.Sh AUTHORS
.An Adrian Chadd Aq Mt adrian@FreeBSD.org

View File

@ -1,314 +0,0 @@
/*
* Copyright (c) 2015 Adrian Chadd <adrian@FreeBSD.org>
* 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 <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/cpuset.h>
#include <sys/domainset.h>
#include <sys/resource.h>
#include <sys/time.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <getopt.h>
#include <libgen.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <unistd.h>
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(int policy)
{
switch (policy) {
case DOMAINSET_POLICY_INVALID:
return ("invalid");
case DOMAINSET_POLICY_ROUNDROBIN:
return ("round-robin");
case DOMAINSET_POLICY_FIRSTTOUCH:
return ("first-touch");
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(int *policy, const char *str)
{
if (strcmp(str, "rr") == 0) {
*policy = DOMAINSET_POLICY_ROUNDROBIN;
return (0);
}
if (strcmp(str, "first-touch-rr") == 0) {
*policy = DOMAINSET_POLICY_FIRSTTOUCH;
return (0);
}
if (strcmp(str, "first-touch") == 0) {
*policy = DOMAINSET_POLICY_FIRSTTOUCH;
return (0);
}
if (strcmp(str, "fixed-domain") == 0) {
*policy = DOMAINSET_POLICY_PREFER;
return (0);
}
if (strcmp(str, "fixed-domain-rr") == 0) {
*policy = DOMAINSET_POLICY_PREFER;
return (0);
}
return (-1);
}
static void
usage(void)
{
printf("usage: numactl --get [--tid/-t <tid>] [--pid/-p <pid>]\n");
printf(" numactl --set [--tid=<tid>] [--pid/-p<pid>]\n");
printf(" [--mempolicy/-l <policy>] [--memdomain/"
"-m <domain>]\n");
printf(" [--cpudomain/-c <domain>]\n");
printf(" numactl [--mempolicy/-l <policy>] [--memdomain/-m "
"<domain>]\n");
printf(" [--cpudomain/-c <domain>] <cmd> ...\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[])
{
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(&policy, optarg) != 0) {
fprintf(stderr,
"Could not parse policy: '%s'\n", optarg);
exit(1);
}
mem_policy_set = 1;
break;
case 'm':
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, 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) {
domainset_t mask;
error = cpuset_getdomain(CPU_LEVEL_WHICH, which, id,
sizeof(mask), &mask, &policy);
if (error != 0)
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, 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);
}