Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*-
|
2017-11-27 15:20:12 +00:00
|
|
|
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
|
|
|
*
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
* Copyright (c) 2008, Jeffrey Roberson <jeff@freebsd.org>
|
|
|
|
* All rights reserved.
|
2008-04-04 01:22:04 +00:00
|
|
|
*
|
|
|
|
* Copyright (c) 2008 Nokia Corporation
|
|
|
|
* All rights reserved.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*
|
|
|
|
* 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 unmodified, 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 ``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 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$");
|
|
|
|
|
2008-07-07 21:32:02 +00:00
|
|
|
#include "opt_ddb.h"
|
2022-05-11 07:40:39 +00:00
|
|
|
#include "opt_ktrace.h"
|
2008-07-07 21:32:02 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/systm.h>
|
2018-03-29 02:54:50 +00:00
|
|
|
#include <sys/sysctl.h>
|
|
|
|
#include <sys/ctype.h>
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#include <sys/sysproto.h>
|
2009-05-27 14:11:23 +00:00
|
|
|
#include <sys/jail.h>
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#include <sys/kernel.h>
|
|
|
|
#include <sys/lock.h>
|
|
|
|
#include <sys/malloc.h>
|
|
|
|
#include <sys/mutex.h>
|
|
|
|
#include <sys/priv.h>
|
|
|
|
#include <sys/proc.h>
|
|
|
|
#include <sys/refcount.h>
|
|
|
|
#include <sys/sched.h>
|
|
|
|
#include <sys/smp.h>
|
|
|
|
#include <sys/syscallsubr.h>
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
#include <sys/sysent.h>
|
2017-05-24 00:58:30 +00:00
|
|
|
#include <sys/capsicum.h>
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#include <sys/cpuset.h>
|
2018-01-12 22:48:23 +00:00
|
|
|
#include <sys/domainset.h>
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#include <sys/sx.h>
|
|
|
|
#include <sys/queue.h>
|
2011-05-31 20:48:58 +00:00
|
|
|
#include <sys/libkern.h>
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#include <sys/limits.h>
|
2008-03-30 11:31:14 +00:00
|
|
|
#include <sys/bus.h>
|
|
|
|
#include <sys/interrupt.h>
|
2018-01-12 22:48:23 +00:00
|
|
|
#include <sys/vmmeter.h>
|
2022-05-11 07:40:39 +00:00
|
|
|
#include <sys/ktrace.h>
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
|
|
|
#include <vm/uma.h>
|
2015-01-08 15:53:13 +00:00
|
|
|
#include <vm/vm.h>
|
2018-01-12 22:48:23 +00:00
|
|
|
#include <vm/vm_object.h>
|
2018-10-01 14:14:21 +00:00
|
|
|
#include <vm/vm_page.h>
|
|
|
|
#include <vm/vm_pageout.h>
|
2018-03-29 02:54:50 +00:00
|
|
|
#include <vm/vm_extern.h>
|
2018-10-01 14:14:21 +00:00
|
|
|
#include <vm/vm_param.h>
|
|
|
|
#include <vm/vm_phys.h>
|
|
|
|
#include <vm/vm_pagequeue.h>
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
2008-07-07 21:32:02 +00:00
|
|
|
#ifdef DDB
|
|
|
|
#include <ddb/ddb.h>
|
|
|
|
#endif /* DDB */
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* cpusets provide a mechanism for creating and manipulating sets of
|
|
|
|
* processors for the purpose of constraining the scheduling of threads to
|
|
|
|
* specific processors.
|
|
|
|
*
|
|
|
|
* Each process belongs to an identified set, by default this is set 1. Each
|
|
|
|
* thread may further restrict the cpus it may run on to a subset of this
|
|
|
|
* named set. This creates an anonymous set which other threads and processes
|
|
|
|
* may not join by number.
|
|
|
|
*
|
|
|
|
* The named set is referred to herein as the 'base' set to avoid ambiguity.
|
|
|
|
* This set is usually a child of a 'root' set while the anonymous set may
|
|
|
|
* simply be referred to as a mask. In the syscall api these are referred to
|
|
|
|
* as the ROOT, CPUSET, and MASK levels where CPUSET is called 'base' here.
|
|
|
|
*
|
|
|
|
* Threads inherit their set from their creator whether it be anonymous or
|
|
|
|
* not. This means that anonymous sets are immutable because they may be
|
|
|
|
* shared. To modify an anonymous set a new set is created with the desired
|
|
|
|
* mask and the same parent as the existing anonymous set. This gives the
|
2009-10-26 17:42:03 +00:00
|
|
|
* illusion of each thread having a private mask.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*
|
|
|
|
* Via the syscall apis a user may ask to retrieve or modify the root, base,
|
|
|
|
* or mask that is discovered via a pid, tid, or setid. Modifying a set
|
|
|
|
* modifies all numbered and anonymous child sets to comply with the new mask.
|
|
|
|
* Modifying a pid or tid's mask applies only to that tid but must still
|
|
|
|
* exist within the assigned parent set.
|
|
|
|
*
|
2009-10-26 18:32:06 +00:00
|
|
|
* A thread may not be assigned to a group separate from other threads in
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
* the process. This is to remove ambiguity when the setid is queried with
|
|
|
|
* a pid argument. There is no other technical limitation.
|
|
|
|
*
|
|
|
|
* This somewhat complex arrangement is intended to make it easy for
|
|
|
|
* applications to query available processors and bind their threads to
|
|
|
|
* specific processors while also allowing administrators to dynamically
|
|
|
|
* reprovision by changing sets which apply to groups of processes.
|
|
|
|
*
|
|
|
|
* A simple application should not concern itself with sets at all and
|
|
|
|
* rather apply masks to its own threads via CPU_WHICH_TID and a -1 id
|
2009-10-26 17:42:03 +00:00
|
|
|
* meaning 'curthread'. It may query available cpus for that tid with a
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
* getaffinity call using (CPU_LEVEL_CPUSET, CPU_WHICH_PID, -1, ...).
|
|
|
|
*/
|
2018-03-29 02:54:50 +00:00
|
|
|
|
|
|
|
LIST_HEAD(domainlist, domainset);
|
2021-04-14 16:56:39 +00:00
|
|
|
struct domainset __read_mostly domainset_firsttouch;
|
2018-10-30 18:26:34 +00:00
|
|
|
struct domainset __read_mostly domainset_fixed[MAXMEMDOM];
|
2021-04-14 16:56:39 +00:00
|
|
|
struct domainset __read_mostly domainset_interleave;
|
2018-10-20 17:36:00 +00:00
|
|
|
struct domainset __read_mostly domainset_prefer[MAXMEMDOM];
|
|
|
|
struct domainset __read_mostly domainset_roundrobin;
|
2018-03-29 02:54:50 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
static uma_zone_t cpuset_zone;
|
2018-01-12 22:48:23 +00:00
|
|
|
static uma_zone_t domainset_zone;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
static struct mtx cpuset_lock;
|
|
|
|
static struct setlist cpuset_ids;
|
2018-01-12 22:48:23 +00:00
|
|
|
static struct domainlist cpuset_domains;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
static struct unrhdr *cpuset_unr;
|
2018-03-29 02:54:50 +00:00
|
|
|
static struct cpuset *cpuset_zero, *cpuset_default, *cpuset_kernel;
|
2021-04-14 16:56:39 +00:00
|
|
|
static struct domainset *domainset0, *domainset2;
|
2023-01-29 12:35:18 +00:00
|
|
|
u_int cpusetsizemin = 1;
|
2008-03-30 11:31:14 +00:00
|
|
|
|
2010-11-01 00:42:25 +00:00
|
|
|
/* Return the size of cpuset_t at the kernel level */
|
2015-05-14 15:14:03 +00:00
|
|
|
SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD | CTLFLAG_CAPRD,
|
2014-10-21 07:31:21 +00:00
|
|
|
SYSCTL_NULL_INT_PTR, sizeof(cpuset_t), "sizeof(cpuset_t)");
|
2010-11-01 00:42:25 +00:00
|
|
|
|
2023-01-29 12:35:18 +00:00
|
|
|
/* Return the minimum size of cpuset_t allowed by the kernel */
|
|
|
|
SYSCTL_UINT(_kern_sched, OID_AUTO, cpusetsizemin,
|
|
|
|
CTLFLAG_RD | CTLFLAG_CAPRD, &cpusetsizemin, 0,
|
|
|
|
"The minimum size of cpuset_t allowed by the kernel");
|
|
|
|
|
2008-03-30 11:31:14 +00:00
|
|
|
cpuset_t *cpuset_root;
|
2015-01-08 15:53:13 +00:00
|
|
|
cpuset_t cpuset_domain[MAXMEMDOM];
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
2023-01-30 16:28:54 +00:00
|
|
|
static int cpuset_which2(cpuwhich_t *, id_t, struct proc **, struct thread **,
|
|
|
|
struct cpuset **);
|
2018-01-12 22:48:23 +00:00
|
|
|
static int domainset_valid(const struct domainset *, const struct domainset *);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the first non-anonymous set starting from 'set'.
|
|
|
|
*/
|
|
|
|
static struct cpuset *
|
|
|
|
cpuset_getbase(struct cpuset *set)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (set->cs_id == CPUSET_INVALID)
|
|
|
|
set = set->cs_parent;
|
|
|
|
return (set);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Walks up the tree from 'set' to find the root.
|
|
|
|
*/
|
|
|
|
static struct cpuset *
|
|
|
|
cpuset_getroot(struct cpuset *set)
|
|
|
|
{
|
|
|
|
|
|
|
|
while ((set->cs_flags & CPU_SET_ROOT) == 0 && set->cs_parent != NULL)
|
|
|
|
set = set->cs_parent;
|
|
|
|
return (set);
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* Acquire a reference to a cpuset, all pointers must be tracked with refs.
|
|
|
|
*/
|
|
|
|
struct cpuset *
|
|
|
|
cpuset_ref(struct cpuset *set)
|
|
|
|
{
|
|
|
|
|
|
|
|
refcount_acquire(&set->cs_ref);
|
|
|
|
return (set);
|
|
|
|
}
|
|
|
|
|
2008-07-07 20:45:55 +00:00
|
|
|
/*
|
|
|
|
* Walks up the tree from 'set' to find the root. Returns the root
|
|
|
|
* referenced.
|
|
|
|
*/
|
|
|
|
static struct cpuset *
|
|
|
|
cpuset_refroot(struct cpuset *set)
|
|
|
|
{
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
return (cpuset_ref(cpuset_getroot(set)));
|
2008-07-07 20:45:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find the first non-anonymous set starting from 'set'. Returns this set
|
|
|
|
* referenced. May return the passed in set with an extra ref if it is
|
|
|
|
* not anonymous.
|
|
|
|
*/
|
|
|
|
static struct cpuset *
|
|
|
|
cpuset_refbase(struct cpuset *set)
|
|
|
|
{
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
return (cpuset_ref(cpuset_getbase(set)));
|
2008-07-07 20:45:55 +00:00
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
2009-10-26 17:42:03 +00:00
|
|
|
* Release a reference in a context where it is safe to allocate.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
cpuset_rel(struct cpuset *set)
|
|
|
|
{
|
|
|
|
cpusetid_t id;
|
|
|
|
|
2020-12-08 18:45:47 +00:00
|
|
|
if (refcount_release_if_not_last(&set->cs_ref))
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
return;
|
|
|
|
mtx_lock_spin(&cpuset_lock);
|
2020-12-08 18:45:47 +00:00
|
|
|
if (!refcount_release(&set->cs_ref)) {
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
return;
|
|
|
|
}
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
LIST_REMOVE(set, cs_siblings);
|
|
|
|
id = set->cs_id;
|
|
|
|
if (id != CPUSET_INVALID)
|
|
|
|
LIST_REMOVE(set, cs_link);
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
cpuset_rel(set->cs_parent);
|
|
|
|
uma_zfree(cpuset_zone, set);
|
|
|
|
if (id != CPUSET_INVALID)
|
|
|
|
free_unr(cpuset_unr, id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Deferred release must be used when in a context that is not safe to
|
|
|
|
* allocate/free. This places any unreferenced sets on the list 'head'.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cpuset_rel_defer(struct setlist *head, struct cpuset *set)
|
|
|
|
{
|
|
|
|
|
2020-12-08 18:45:47 +00:00
|
|
|
if (refcount_release_if_not_last(&set->cs_ref))
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
return;
|
|
|
|
mtx_lock_spin(&cpuset_lock);
|
2020-12-08 18:45:47 +00:00
|
|
|
if (!refcount_release(&set->cs_ref)) {
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
return;
|
|
|
|
}
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
LIST_REMOVE(set, cs_siblings);
|
|
|
|
if (set->cs_id != CPUSET_INVALID)
|
|
|
|
LIST_REMOVE(set, cs_link);
|
|
|
|
LIST_INSERT_HEAD(head, set, cs_link);
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Complete a deferred release. Removes the set from the list provided to
|
|
|
|
* cpuset_rel_defer.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cpuset_rel_complete(struct cpuset *set)
|
|
|
|
{
|
2020-12-08 18:44:06 +00:00
|
|
|
cpusetid_t id;
|
|
|
|
|
|
|
|
id = set->cs_id;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
LIST_REMOVE(set, cs_link);
|
|
|
|
cpuset_rel(set->cs_parent);
|
|
|
|
uma_zfree(cpuset_zone, set);
|
2020-12-08 18:44:06 +00:00
|
|
|
if (id != CPUSET_INVALID)
|
|
|
|
free_unr(cpuset_unr, id);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Find a set based on an id. Returns it with a ref.
|
|
|
|
*/
|
|
|
|
static struct cpuset *
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
cpuset_lookup(cpusetid_t setid, struct thread *td)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
|
|
|
|
if (setid == CPUSET_INVALID)
|
|
|
|
return (NULL);
|
|
|
|
mtx_lock_spin(&cpuset_lock);
|
|
|
|
LIST_FOREACH(set, &cpuset_ids, cs_link)
|
|
|
|
if (set->cs_id == setid)
|
|
|
|
break;
|
|
|
|
if (set)
|
|
|
|
cpuset_ref(set);
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
|
|
|
|
KASSERT(td != NULL, ("[%s:%d] td is NULL", __func__, __LINE__));
|
|
|
|
if (set != NULL && jailed(td->td_ucred)) {
|
2009-05-27 14:11:23 +00:00
|
|
|
struct cpuset *jset, *tset;
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
|
2009-05-27 14:11:23 +00:00
|
|
|
jset = td->td_ucred->cr_prison->pr_cpuset;
|
|
|
|
for (tset = set; tset != NULL; tset = tset->cs_parent)
|
|
|
|
if (tset == jset)
|
|
|
|
break;
|
|
|
|
if (tset == NULL) {
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
cpuset_rel(set);
|
|
|
|
set = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
return (set);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2020-11-25 02:12:24 +00:00
|
|
|
* Initialize a set in the space provided in 'set' with the provided parameters.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
* The set is returned with a single ref. May return EDEADLK if the set
|
|
|
|
* will have no valid cpu based on restrictions from the parent.
|
|
|
|
*/
|
|
|
|
static int
|
2020-11-25 02:12:24 +00:00
|
|
|
cpuset_init(struct cpuset *set, struct cpuset *parent,
|
2018-01-12 22:48:23 +00:00
|
|
|
const cpuset_t *mask, struct domainset *domain, cpusetid_t id)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
if (domain == NULL)
|
|
|
|
domain = parent->cs_domain;
|
|
|
|
if (mask == NULL)
|
|
|
|
mask = &parent->cs_mask;
|
2008-03-05 01:49:20 +00:00
|
|
|
if (!CPU_OVERLAP(&parent->cs_mask, mask))
|
|
|
|
return (EDEADLK);
|
2018-01-12 22:48:23 +00:00
|
|
|
/* The domain must be prepared ahead of time. */
|
|
|
|
if (!domainset_valid(parent->cs_domain, domain))
|
|
|
|
return (EDEADLK);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
CPU_COPY(mask, &set->cs_mask);
|
|
|
|
LIST_INIT(&set->cs_children);
|
|
|
|
refcount_init(&set->cs_ref, 1);
|
|
|
|
set->cs_flags = 0;
|
|
|
|
mtx_lock_spin(&cpuset_lock);
|
2018-01-12 22:48:23 +00:00
|
|
|
set->cs_domain = domain;
|
Make CPU_SET macros compliant with other implementations
The introduction of <sched.h> improved compatibility with some 3rd
party software, but caused the configure scripts of some ports to
assume that they were run in a GLIBC compatible environment.
Parts of sched.h were made conditional on -D_WITH_CPU_SET_T being
added to ports, but there still were compatibility issues due to
invalid assumptions made in autoconfigure scripts.
The differences between the FreeBSD version of macros like CPU_AND,
CPU_OR, etc. and the GLIBC versions was in the number of arguments:
FreeBSD used a 2-address scheme (one source argument is also used as
the destination of the operation), while GLIBC uses a 3-adderess
scheme (2 source operands and a separately passed destination).
The GLIBC scheme provides a super-set of the functionality of the
FreeBSD macros, since it does not prevent passing the same variable
as source and destination arguments. In code that wanted to preserve
both source arguments, the FreeBSD macros required a temporary copy of
one of the source arguments.
This patch set allows to unconditionally provide functions and macros
expected by 3rd party software written for GLIBC based systems, but
breaks builds of externally maintained sources that use any of the
following macros: CPU_AND, CPU_ANDNOT, CPU_OR, CPU_XOR.
One contributed driver (contrib/ofed/libmlx5) has been patched to
support both the old and the new CPU_OR signatures. If this commit
is merged to -STABLE, the version test will have to be extended to
cover more ranges.
Ports that have added -D_WITH_CPU_SET_T to build on -CURRENT do
no longer require that option.
The FreeBSD version has been bumped to 1400046 to reflect this
incompatible change.
Reviewed by: kib
MFC after: 2 weeks
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D33451
2021-12-30 11:20:32 +00:00
|
|
|
CPU_AND(&set->cs_mask, &set->cs_mask, &parent->cs_mask);
|
2008-03-05 01:49:20 +00:00
|
|
|
set->cs_id = id;
|
|
|
|
set->cs_parent = cpuset_ref(parent);
|
|
|
|
LIST_INSERT_HEAD(&parent->cs_children, set, cs_siblings);
|
|
|
|
if (set->cs_id != CPUSET_INVALID)
|
|
|
|
LIST_INSERT_HEAD(&cpuset_ids, set, cs_link);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
|
2008-03-05 01:49:20 +00:00
|
|
|
return (0);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a new non-anonymous set with the requested parent and mask. May
|
|
|
|
* return failures if the mask is invalid or a new number can not be
|
|
|
|
* allocated.
|
2020-11-25 01:42:32 +00:00
|
|
|
*
|
|
|
|
* If *setp is not NULL, then it will be used as-is. The caller must take
|
|
|
|
* into account that *setp will be inserted at the head of cpuset_ids and
|
|
|
|
* plan any potentially conflicting cs_link usage accordingly.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*/
|
|
|
|
static int
|
2011-03-08 14:18:21 +00:00
|
|
|
cpuset_create(struct cpuset **setp, struct cpuset *parent, const cpuset_t *mask)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
cpusetid_t id;
|
|
|
|
int error;
|
2020-11-25 01:42:32 +00:00
|
|
|
bool dofree;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
|
|
|
id = alloc_unr(cpuset_unr);
|
|
|
|
if (id == -1)
|
|
|
|
return (ENFILE);
|
2020-11-25 01:42:32 +00:00
|
|
|
dofree = (*setp == NULL);
|
|
|
|
if (*setp != NULL)
|
|
|
|
set = *setp;
|
|
|
|
else
|
|
|
|
*setp = set = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
|
2020-11-25 02:12:24 +00:00
|
|
|
error = cpuset_init(set, parent, mask, NULL, id);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error == 0)
|
|
|
|
return (0);
|
|
|
|
free_unr(cpuset_unr, id);
|
2020-11-25 01:42:32 +00:00
|
|
|
if (dofree)
|
|
|
|
uma_zfree(cpuset_zone, set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
static void
|
|
|
|
cpuset_freelist_add(struct setlist *list, int count)
|
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
set = uma_zalloc(cpuset_zone, M_ZERO | M_WAITOK);
|
|
|
|
LIST_INSERT_HEAD(list, set, cs_link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cpuset_freelist_init(struct setlist *list, int count)
|
|
|
|
{
|
|
|
|
|
|
|
|
LIST_INIT(list);
|
|
|
|
cpuset_freelist_add(list, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cpuset_freelist_free(struct setlist *list)
|
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
|
|
|
|
while ((set = LIST_FIRST(list)) != NULL) {
|
|
|
|
LIST_REMOVE(set, cs_link);
|
|
|
|
uma_zfree(cpuset_zone, set);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
domainset_freelist_add(struct domainlist *list, int count)
|
|
|
|
{
|
|
|
|
struct domainset *set;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
set = uma_zalloc(domainset_zone, M_ZERO | M_WAITOK);
|
|
|
|
LIST_INSERT_HEAD(list, set, ds_link);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
domainset_freelist_init(struct domainlist *list, int count)
|
|
|
|
{
|
|
|
|
|
|
|
|
LIST_INIT(list);
|
|
|
|
domainset_freelist_add(list, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
domainset_freelist_free(struct domainlist *list)
|
|
|
|
{
|
|
|
|
struct domainset *set;
|
|
|
|
|
|
|
|
while ((set = LIST_FIRST(list)) != NULL) {
|
|
|
|
LIST_REMOVE(set, ds_link);
|
|
|
|
uma_zfree(domainset_zone, set);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Copy a domainset preserving mask and policy. */
|
|
|
|
static void
|
|
|
|
domainset_copy(const struct domainset *from, struct domainset *to)
|
|
|
|
{
|
|
|
|
|
|
|
|
DOMAINSET_COPY(&from->ds_mask, &to->ds_mask);
|
|
|
|
to->ds_policy = from->ds_policy;
|
|
|
|
to->ds_prefer = from->ds_prefer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return 1 if mask and policy are equal, otherwise 0. */
|
|
|
|
static int
|
|
|
|
domainset_equal(const struct domainset *one, const struct domainset *two)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (DOMAINSET_CMP(&one->ds_mask, &two->ds_mask) == 0 &&
|
|
|
|
one->ds_policy == two->ds_policy &&
|
|
|
|
one->ds_prefer == two->ds_prefer);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Return 1 if child is a valid subset of parent. */
|
|
|
|
static int
|
|
|
|
domainset_valid(const struct domainset *parent, const struct domainset *child)
|
|
|
|
{
|
|
|
|
if (child->ds_policy != DOMAINSET_POLICY_PREFER)
|
|
|
|
return (DOMAINSET_SUBSET(&parent->ds_mask, &child->ds_mask));
|
|
|
|
return (DOMAINSET_ISSET(child->ds_prefer, &parent->ds_mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
domainset_restrict(const struct domainset *parent,
|
|
|
|
const struct domainset *child)
|
|
|
|
{
|
|
|
|
if (child->ds_policy != DOMAINSET_POLICY_PREFER)
|
|
|
|
return (DOMAINSET_OVERLAP(&parent->ds_mask, &child->ds_mask));
|
|
|
|
return (DOMAINSET_ISSET(child->ds_prefer, &parent->ds_mask));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lookup or create a domainset. The key is provided in ds_mask and
|
|
|
|
* ds_policy. If the domainset does not yet exist the storage in
|
|
|
|
* 'domain' is used to insert. Otherwise this storage is freed to the
|
|
|
|
* domainset_zone and the existing domainset is returned.
|
|
|
|
*/
|
|
|
|
static struct domainset *
|
|
|
|
_domainset_create(struct domainset *domain, struct domainlist *freelist)
|
|
|
|
{
|
|
|
|
struct domainset *ndomain;
|
2019-08-27 15:42:08 +00:00
|
|
|
int i, j;
|
2018-01-12 22:48:23 +00:00
|
|
|
|
2018-10-22 20:13:51 +00:00
|
|
|
KASSERT(domain->ds_cnt <= vm_ndomains,
|
|
|
|
("invalid domain count in domainset %p", domain));
|
|
|
|
KASSERT(domain->ds_policy != DOMAINSET_POLICY_PREFER ||
|
|
|
|
domain->ds_prefer < vm_ndomains,
|
|
|
|
("invalid preferred domain in domains %p", domain));
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
mtx_lock_spin(&cpuset_lock);
|
|
|
|
LIST_FOREACH(ndomain, &cpuset_domains, ds_link)
|
|
|
|
if (domainset_equal(ndomain, domain))
|
|
|
|
break;
|
|
|
|
/*
|
|
|
|
* If the domain does not yet exist we insert it and initialize
|
|
|
|
* various iteration helpers which are not part of the key.
|
|
|
|
*/
|
|
|
|
if (ndomain == NULL) {
|
|
|
|
LIST_INSERT_HEAD(&cpuset_domains, domain, ds_link);
|
|
|
|
domain->ds_cnt = DOMAINSET_COUNT(&domain->ds_mask);
|
2019-08-27 15:42:08 +00:00
|
|
|
for (i = 0, j = 0; i < DOMAINSET_FLS(&domain->ds_mask); i++)
|
2018-03-29 02:54:50 +00:00
|
|
|
if (DOMAINSET_ISSET(i, &domain->ds_mask))
|
|
|
|
domain->ds_order[j++] = i;
|
2018-01-12 22:48:23 +00:00
|
|
|
}
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
if (ndomain == NULL)
|
|
|
|
return (domain);
|
|
|
|
if (freelist != NULL)
|
|
|
|
LIST_INSERT_HEAD(freelist, domain, ds_link);
|
|
|
|
else
|
|
|
|
uma_zfree(domainset_zone, domain);
|
|
|
|
return (ndomain);
|
2020-09-01 22:12:32 +00:00
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
}
|
|
|
|
|
2018-10-01 14:14:21 +00:00
|
|
|
/*
|
2018-10-30 17:57:40 +00:00
|
|
|
* Are any of the domains in the mask empty? If so, silently
|
|
|
|
* remove them and update the domainset accordingly. If only empty
|
|
|
|
* domains are present, we must return failure.
|
2018-10-01 14:14:21 +00:00
|
|
|
*/
|
|
|
|
static bool
|
|
|
|
domainset_empty_vm(struct domainset *domain)
|
|
|
|
{
|
2019-08-27 14:06:34 +00:00
|
|
|
domainset_t empty;
|
|
|
|
int i, j;
|
|
|
|
|
|
|
|
DOMAINSET_ZERO(&empty);
|
|
|
|
for (i = 0; i < vm_ndomains; i++)
|
|
|
|
if (VM_DOMAIN_EMPTY(i))
|
|
|
|
DOMAINSET_SET(i, &empty);
|
|
|
|
if (DOMAINSET_SUBSET(&empty, &domain->ds_mask))
|
|
|
|
return (true);
|
|
|
|
|
|
|
|
/* Remove empty domains from the set and recompute. */
|
2019-12-13 09:32:16 +00:00
|
|
|
DOMAINSET_ANDNOT(&domain->ds_mask, &empty);
|
2018-10-30 17:57:40 +00:00
|
|
|
domain->ds_cnt = DOMAINSET_COUNT(&domain->ds_mask);
|
2019-08-27 14:06:34 +00:00
|
|
|
for (i = j = 0; i < DOMAINSET_FLS(&domain->ds_mask); i++)
|
2018-10-30 17:57:40 +00:00
|
|
|
if (DOMAINSET_ISSET(i, &domain->ds_mask))
|
|
|
|
domain->ds_order[j++] = i;
|
2019-08-27 14:06:34 +00:00
|
|
|
|
|
|
|
/* Convert a PREFER policy referencing an empty domain to RR. */
|
|
|
|
if (domain->ds_policy == DOMAINSET_POLICY_PREFER &&
|
|
|
|
DOMAINSET_ISSET(domain->ds_prefer, &empty)) {
|
|
|
|
domain->ds_policy = DOMAINSET_POLICY_ROUNDROBIN;
|
|
|
|
domain->ds_prefer = -1;
|
2018-10-01 14:14:21 +00:00
|
|
|
}
|
|
|
|
|
2019-08-27 14:06:34 +00:00
|
|
|
return (false);
|
2018-10-01 14:14:21 +00:00
|
|
|
}
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
/*
|
|
|
|
* Create or lookup a domainset based on the key held in 'domain'.
|
|
|
|
*/
|
2018-03-29 02:54:50 +00:00
|
|
|
struct domainset *
|
2018-01-12 22:48:23 +00:00
|
|
|
domainset_create(const struct domainset *domain)
|
|
|
|
{
|
|
|
|
struct domainset *ndomain;
|
|
|
|
|
2018-03-29 02:54:50 +00:00
|
|
|
/*
|
|
|
|
* Validate the policy. It must specify a useable policy number with
|
|
|
|
* only valid domains. Preferred must include the preferred domain
|
|
|
|
* in the mask.
|
|
|
|
*/
|
|
|
|
if (domain->ds_policy <= DOMAINSET_POLICY_INVALID ||
|
|
|
|
domain->ds_policy > DOMAINSET_POLICY_MAX)
|
|
|
|
return (NULL);
|
|
|
|
if (domain->ds_policy == DOMAINSET_POLICY_PREFER &&
|
|
|
|
!DOMAINSET_ISSET(domain->ds_prefer, &domain->ds_mask))
|
|
|
|
return (NULL);
|
2021-04-14 16:56:39 +00:00
|
|
|
if (!DOMAINSET_SUBSET(&domainset0->ds_mask, &domain->ds_mask))
|
2018-03-29 02:54:50 +00:00
|
|
|
return (NULL);
|
2018-01-12 22:48:23 +00:00
|
|
|
ndomain = uma_zalloc(domainset_zone, M_WAITOK | M_ZERO);
|
|
|
|
domainset_copy(domain, ndomain);
|
|
|
|
return _domainset_create(ndomain, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Update thread domainset pointers.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
domainset_notify(void)
|
|
|
|
{
|
|
|
|
struct thread *td;
|
|
|
|
struct proc *p;
|
|
|
|
|
|
|
|
sx_slock(&allproc_lock);
|
|
|
|
FOREACH_PROC_IN_SYSTEM(p) {
|
|
|
|
PROC_LOCK(p);
|
|
|
|
if (p->p_state == PRS_NEW) {
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
FOREACH_THREAD_IN_PROC(p, td) {
|
|
|
|
thread_lock(td);
|
|
|
|
td->td_domain.dr_policy = td->td_cpuset->cs_domain;
|
|
|
|
thread_unlock(td);
|
|
|
|
}
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
}
|
|
|
|
sx_sunlock(&allproc_lock);
|
2018-03-29 02:54:50 +00:00
|
|
|
kernel_object->domain.dr_policy = cpuset_kernel->cs_domain;
|
2018-01-12 22:48:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Create a new set that is a subset of a parent.
|
|
|
|
*/
|
|
|
|
static struct domainset *
|
|
|
|
domainset_shadow(const struct domainset *pdomain,
|
|
|
|
const struct domainset *domain, struct domainlist *freelist)
|
|
|
|
{
|
|
|
|
struct domainset *ndomain;
|
|
|
|
|
|
|
|
ndomain = LIST_FIRST(freelist);
|
|
|
|
LIST_REMOVE(ndomain, ds_link);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Initialize the key from the request.
|
|
|
|
*/
|
|
|
|
domainset_copy(domain, ndomain);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Restrict the key by the parent.
|
|
|
|
*/
|
|
|
|
DOMAINSET_AND(&ndomain->ds_mask, &pdomain->ds_mask);
|
|
|
|
|
|
|
|
return _domainset_create(ndomain, freelist);
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* Recursively check for errors that would occur from applying mask to
|
|
|
|
* the tree of sets starting at 'set'. Checks for sets that would become
|
|
|
|
* empty as well as RDONLY flags.
|
|
|
|
*/
|
|
|
|
static int
|
2020-12-08 18:47:22 +00:00
|
|
|
cpuset_testupdate(struct cpuset *set, cpuset_t *mask, int augment_mask)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *nset;
|
|
|
|
cpuset_t newmask;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
mtx_assert(&cpuset_lock, MA_OWNED);
|
|
|
|
if (set->cs_flags & CPU_SET_RDONLY)
|
|
|
|
return (EPERM);
|
2020-12-08 18:47:22 +00:00
|
|
|
if (augment_mask) {
|
Make CPU_SET macros compliant with other implementations
The introduction of <sched.h> improved compatibility with some 3rd
party software, but caused the configure scripts of some ports to
assume that they were run in a GLIBC compatible environment.
Parts of sched.h were made conditional on -D_WITH_CPU_SET_T being
added to ports, but there still were compatibility issues due to
invalid assumptions made in autoconfigure scripts.
The differences between the FreeBSD version of macros like CPU_AND,
CPU_OR, etc. and the GLIBC versions was in the number of arguments:
FreeBSD used a 2-address scheme (one source argument is also used as
the destination of the operation), while GLIBC uses a 3-adderess
scheme (2 source operands and a separately passed destination).
The GLIBC scheme provides a super-set of the functionality of the
FreeBSD macros, since it does not prevent passing the same variable
as source and destination arguments. In code that wanted to preserve
both source arguments, the FreeBSD macros required a temporary copy of
one of the source arguments.
This patch set allows to unconditionally provide functions and macros
expected by 3rd party software written for GLIBC based systems, but
breaks builds of externally maintained sources that use any of the
following macros: CPU_AND, CPU_ANDNOT, CPU_OR, CPU_XOR.
One contributed driver (contrib/ofed/libmlx5) has been patched to
support both the old and the new CPU_OR signatures. If this commit
is merged to -STABLE, the version test will have to be extended to
cover more ranges.
Ports that have added -D_WITH_CPU_SET_T to build on -CURRENT do
no longer require that option.
The FreeBSD version has been bumped to 1400046 to reflect this
incompatible change.
Reviewed by: kib
MFC after: 2 weeks
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D33451
2021-12-30 11:20:32 +00:00
|
|
|
CPU_AND(&newmask, &set->cs_mask, mask);
|
2013-06-06 14:43:19 +00:00
|
|
|
} else
|
|
|
|
CPU_COPY(mask, &newmask);
|
2020-12-08 18:47:22 +00:00
|
|
|
|
|
|
|
if (CPU_EMPTY(&newmask))
|
|
|
|
return (EDEADLK);
|
2008-03-05 01:49:20 +00:00
|
|
|
error = 0;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
LIST_FOREACH(nset, &set->cs_children, cs_siblings)
|
2013-06-06 14:43:19 +00:00
|
|
|
if ((error = cpuset_testupdate(nset, &newmask, 1)) != 0)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Applies the mask 'mask' without checking for empty sets or permissions.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cpuset_update(struct cpuset *set, cpuset_t *mask)
|
|
|
|
{
|
|
|
|
struct cpuset *nset;
|
|
|
|
|
|
|
|
mtx_assert(&cpuset_lock, MA_OWNED);
|
Make CPU_SET macros compliant with other implementations
The introduction of <sched.h> improved compatibility with some 3rd
party software, but caused the configure scripts of some ports to
assume that they were run in a GLIBC compatible environment.
Parts of sched.h were made conditional on -D_WITH_CPU_SET_T being
added to ports, but there still were compatibility issues due to
invalid assumptions made in autoconfigure scripts.
The differences between the FreeBSD version of macros like CPU_AND,
CPU_OR, etc. and the GLIBC versions was in the number of arguments:
FreeBSD used a 2-address scheme (one source argument is also used as
the destination of the operation), while GLIBC uses a 3-adderess
scheme (2 source operands and a separately passed destination).
The GLIBC scheme provides a super-set of the functionality of the
FreeBSD macros, since it does not prevent passing the same variable
as source and destination arguments. In code that wanted to preserve
both source arguments, the FreeBSD macros required a temporary copy of
one of the source arguments.
This patch set allows to unconditionally provide functions and macros
expected by 3rd party software written for GLIBC based systems, but
breaks builds of externally maintained sources that use any of the
following macros: CPU_AND, CPU_ANDNOT, CPU_OR, CPU_XOR.
One contributed driver (contrib/ofed/libmlx5) has been patched to
support both the old and the new CPU_OR signatures. If this commit
is merged to -STABLE, the version test will have to be extended to
cover more ranges.
Ports that have added -D_WITH_CPU_SET_T to build on -CURRENT do
no longer require that option.
The FreeBSD version has been bumped to 1400046 to reflect this
incompatible change.
Reviewed by: kib
MFC after: 2 weeks
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D33451
2021-12-30 11:20:32 +00:00
|
|
|
CPU_AND(&set->cs_mask, &set->cs_mask, mask);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
LIST_FOREACH(nset, &set->cs_children, cs_siblings)
|
|
|
|
cpuset_update(nset, &set->cs_mask);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Modify the set 'set' to use a copy of the mask provided. Apply this new
|
|
|
|
* mask to restrict all children in the tree. Checks for validity before
|
|
|
|
* applying the changes.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
cpuset_modify(struct cpuset *set, cpuset_t *mask)
|
|
|
|
{
|
2008-03-05 01:49:20 +00:00
|
|
|
struct cpuset *root;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
int error;
|
|
|
|
|
2008-06-29 17:58:16 +00:00
|
|
|
error = priv_check(curthread, PRIV_SCHED_CPUSET);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2009-04-28 21:00:50 +00:00
|
|
|
/*
|
2020-12-19 03:30:06 +00:00
|
|
|
* In case we are called from within the jail,
|
2009-04-28 21:00:50 +00:00
|
|
|
* we do not allow modifying the dedicated root
|
|
|
|
* cpuset of the jail but may still allow to
|
2020-12-19 03:30:06 +00:00
|
|
|
* change child sets, including subordinate jails'
|
|
|
|
* roots.
|
2009-04-28 21:00:50 +00:00
|
|
|
*/
|
2020-12-19 03:30:06 +00:00
|
|
|
if ((set->cs_flags & CPU_SET_ROOT) != 0 &&
|
|
|
|
jailed(curthread->td_ucred) &&
|
|
|
|
set == curthread->td_ucred->cr_prison->pr_cpuset)
|
2009-04-28 21:00:50 +00:00
|
|
|
return (EPERM);
|
2008-03-05 01:49:20 +00:00
|
|
|
/*
|
|
|
|
* Verify that we have access to this set of
|
|
|
|
* cpus.
|
|
|
|
*/
|
2020-12-19 03:30:06 +00:00
|
|
|
if ((set->cs_flags & (CPU_SET_ROOT | CPU_SET_RDONLY)) == CPU_SET_ROOT) {
|
|
|
|
KASSERT(set->cs_parent != NULL,
|
|
|
|
("jail.cpuset=%d is not a proper child of parent jail's root.",
|
|
|
|
set->cs_id));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* cpuset_getroot() cannot work here due to how top-level jail
|
|
|
|
* roots are constructed. Top-level jails are parented to
|
|
|
|
* thread0's cpuset (i.e. cpuset 1) rather than the system root.
|
|
|
|
*/
|
|
|
|
root = set->cs_parent;
|
|
|
|
} else {
|
|
|
|
root = cpuset_getroot(set);
|
|
|
|
}
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
mtx_lock_spin(&cpuset_lock);
|
2018-01-12 22:48:23 +00:00
|
|
|
if (root && !CPU_SUBSET(&root->cs_mask, mask)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2013-06-06 14:43:19 +00:00
|
|
|
error = cpuset_testupdate(set, mask, 0);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
CPU_COPY(mask, &set->cs_mask);
|
2013-06-06 14:43:19 +00:00
|
|
|
cpuset_update(set, mask);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
out:
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
/*
|
|
|
|
* Recursively check for errors that would occur from applying mask to
|
|
|
|
* the tree of sets starting at 'set'. Checks for sets that would become
|
|
|
|
* empty as well as RDONLY flags.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
cpuset_testupdate_domain(struct cpuset *set, struct domainset *dset,
|
2020-12-08 18:47:22 +00:00
|
|
|
struct domainset *orig, int *count, int augment_mask __unused)
|
2018-01-12 22:48:23 +00:00
|
|
|
{
|
|
|
|
struct cpuset *nset;
|
|
|
|
struct domainset *domain;
|
|
|
|
struct domainset newset;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
mtx_assert(&cpuset_lock, MA_OWNED);
|
|
|
|
if (set->cs_flags & CPU_SET_RDONLY)
|
|
|
|
return (EPERM);
|
|
|
|
domain = set->cs_domain;
|
|
|
|
domainset_copy(domain, &newset);
|
|
|
|
if (!domainset_equal(domain, orig)) {
|
|
|
|
if (!domainset_restrict(domain, dset))
|
|
|
|
return (EDEADLK);
|
|
|
|
DOMAINSET_AND(&newset.ds_mask, &dset->ds_mask);
|
|
|
|
/* Count the number of domains that are changing. */
|
|
|
|
(*count)++;
|
|
|
|
}
|
|
|
|
error = 0;
|
|
|
|
LIST_FOREACH(nset, &set->cs_children, cs_siblings)
|
|
|
|
if ((error = cpuset_testupdate_domain(nset, &newset, domain,
|
|
|
|
count, 1)) != 0)
|
|
|
|
break;
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Applies the mask 'mask' without checking for empty sets or permissions.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
cpuset_update_domain(struct cpuset *set, struct domainset *domain,
|
|
|
|
struct domainset *orig, struct domainlist *domains)
|
|
|
|
{
|
|
|
|
struct cpuset *nset;
|
|
|
|
|
|
|
|
mtx_assert(&cpuset_lock, MA_OWNED);
|
|
|
|
/*
|
|
|
|
* If this domainset has changed from the parent we must calculate
|
|
|
|
* a new set. Otherwise it simply inherits from the parent. When
|
|
|
|
* we inherit from the parent we get a new mask and policy. If the
|
|
|
|
* set is modified from the parent we keep the policy and only
|
|
|
|
* update the mask.
|
|
|
|
*/
|
|
|
|
if (set->cs_domain != orig) {
|
|
|
|
orig = set->cs_domain;
|
|
|
|
set->cs_domain = domainset_shadow(domain, orig, domains);
|
|
|
|
} else
|
|
|
|
set->cs_domain = domain;
|
|
|
|
LIST_FOREACH(nset, &set->cs_children, cs_siblings)
|
|
|
|
cpuset_update_domain(nset, set->cs_domain, orig, domains);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Modify the set 'set' to use a copy the domainset provided. Apply this new
|
|
|
|
* mask to restrict all children in the tree. Checks for validity before
|
|
|
|
* applying the changes.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
cpuset_modify_domain(struct cpuset *set, struct domainset *domain)
|
|
|
|
{
|
|
|
|
struct domainlist domains;
|
|
|
|
struct domainset temp;
|
|
|
|
struct domainset *dset;
|
|
|
|
struct cpuset *root;
|
|
|
|
int ndomains, needed;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
error = priv_check(curthread, PRIV_SCHED_CPUSET);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
/*
|
|
|
|
* In case we are called from within the jail
|
|
|
|
* we do not allow modifying the dedicated root
|
|
|
|
* cpuset of the jail but may still allow to
|
|
|
|
* change child sets.
|
|
|
|
*/
|
|
|
|
if (jailed(curthread->td_ucred) &&
|
|
|
|
set->cs_flags & CPU_SET_ROOT)
|
|
|
|
return (EPERM);
|
|
|
|
domainset_freelist_init(&domains, 0);
|
|
|
|
domain = domainset_create(domain);
|
2020-11-28 01:21:11 +00:00
|
|
|
ndomains = 0;
|
|
|
|
|
|
|
|
mtx_lock_spin(&cpuset_lock);
|
|
|
|
for (;;) {
|
2018-01-12 22:48:23 +00:00
|
|
|
root = cpuset_getroot(set);
|
|
|
|
dset = root->cs_domain;
|
|
|
|
/*
|
|
|
|
* Verify that we have access to this set of domains.
|
|
|
|
*/
|
2019-09-12 16:47:38 +00:00
|
|
|
if (!domainset_valid(dset, domain)) {
|
2018-01-12 22:48:23 +00:00
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* If applying prefer we keep the current set as the fallback.
|
|
|
|
*/
|
|
|
|
if (domain->ds_policy == DOMAINSET_POLICY_PREFER)
|
|
|
|
DOMAINSET_COPY(&set->cs_domain->ds_mask,
|
|
|
|
&domain->ds_mask);
|
|
|
|
/*
|
|
|
|
* Determine whether we can apply this set of domains and
|
|
|
|
* how many new domain structures it will require.
|
|
|
|
*/
|
|
|
|
domainset_copy(domain, &temp);
|
|
|
|
needed = 0;
|
|
|
|
error = cpuset_testupdate_domain(set, &temp, set->cs_domain,
|
|
|
|
&needed, 0);
|
|
|
|
if (error)
|
|
|
|
goto out;
|
2020-11-28 01:21:11 +00:00
|
|
|
if (ndomains >= needed)
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* Dropping the lock; we'll need to re-evaluate again. */
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
domainset_freelist_add(&domains, needed - ndomains);
|
|
|
|
ndomains = needed;
|
|
|
|
mtx_lock_spin(&cpuset_lock);
|
|
|
|
}
|
2018-01-12 22:48:23 +00:00
|
|
|
dset = set->cs_domain;
|
|
|
|
cpuset_update_domain(set, domain, dset, &domains);
|
|
|
|
out:
|
|
|
|
mtx_unlock_spin(&cpuset_lock);
|
|
|
|
domainset_freelist_free(&domains);
|
|
|
|
if (error == 0)
|
|
|
|
domainset_notify();
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* Resolve the 'which' parameter of several cpuset apis.
|
|
|
|
*
|
|
|
|
* For WHICH_PID and WHICH_TID return a locked proc and valid proc/tid. Also
|
|
|
|
* checks for permission via p_cansched().
|
|
|
|
*
|
|
|
|
* For WHICH_SET returns a valid set with a new reference.
|
|
|
|
*
|
|
|
|
* -1 may be supplied for any argument to mean the current proc/thread or
|
|
|
|
* the base set of the current thread. May fail with ESRCH/EPERM.
|
|
|
|
*/
|
2015-06-26 04:14:05 +00:00
|
|
|
int
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
cpuset_which(cpuwhich_t which, id_t id, struct proc **pp, struct thread **tdp,
|
|
|
|
struct cpuset **setp)
|
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
struct thread *td;
|
|
|
|
struct proc *p;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
*pp = p = NULL;
|
|
|
|
*tdp = td = NULL;
|
|
|
|
*setp = set = NULL;
|
|
|
|
switch (which) {
|
|
|
|
case CPU_WHICH_PID:
|
|
|
|
if (id == -1) {
|
|
|
|
PROC_LOCK(curproc);
|
|
|
|
p = curproc;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if ((p = pfind(id)) == NULL)
|
|
|
|
return (ESRCH);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_TID:
|
|
|
|
if (id == -1) {
|
|
|
|
PROC_LOCK(curproc);
|
|
|
|
p = curproc;
|
|
|
|
td = curthread;
|
|
|
|
break;
|
|
|
|
}
|
2010-10-25 13:13:16 +00:00
|
|
|
td = tdfind(id, -1);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (td == NULL)
|
|
|
|
return (ESRCH);
|
2010-10-25 13:13:16 +00:00
|
|
|
p = td->td_proc;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
2023-01-29 13:17:33 +00:00
|
|
|
case CPU_WHICH_TIDPID:
|
|
|
|
if (id == -1) {
|
|
|
|
PROC_LOCK(curproc);
|
|
|
|
td = curthread;
|
|
|
|
p = curproc;
|
|
|
|
} else if (id > PID_MAX) {
|
|
|
|
td = tdfind(id, -1);
|
|
|
|
if (td == NULL)
|
|
|
|
return (ESRCH);
|
|
|
|
p = td->td_proc;
|
|
|
|
} else {
|
|
|
|
p = pfind(id);
|
|
|
|
if (p == NULL)
|
|
|
|
return (ESRCH);
|
|
|
|
}
|
|
|
|
break;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_WHICH_CPUSET:
|
|
|
|
if (id == -1) {
|
|
|
|
thread_lock(curthread);
|
2008-03-30 11:31:14 +00:00
|
|
|
set = cpuset_refbase(curthread->td_cpuset);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_unlock(curthread);
|
|
|
|
} else
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
set = cpuset_lookup(id, curthread);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (set) {
|
|
|
|
*setp = set;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
return (ESRCH);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
case CPU_WHICH_JAIL:
|
|
|
|
{
|
|
|
|
/* Find `set' for prison with given id. */
|
|
|
|
struct prison *pr;
|
|
|
|
|
|
|
|
sx_slock(&allprison_lock);
|
2009-05-27 14:11:23 +00:00
|
|
|
pr = prison_find_child(curthread->td_ucred->cr_prison, id);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
sx_sunlock(&allprison_lock);
|
|
|
|
if (pr == NULL)
|
|
|
|
return (ESRCH);
|
2009-05-27 14:11:23 +00:00
|
|
|
cpuset_ref(pr->pr_cpuset);
|
|
|
|
*setp = pr->pr_cpuset;
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
mtx_unlock(&pr->pr_mtx);
|
2009-05-27 14:11:23 +00:00
|
|
|
return (0);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
}
|
2008-04-11 03:26:41 +00:00
|
|
|
case CPU_WHICH_IRQ:
|
2015-01-08 15:53:13 +00:00
|
|
|
case CPU_WHICH_DOMAIN:
|
2008-04-11 03:26:41 +00:00
|
|
|
return (0);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
default:
|
|
|
|
return (EINVAL);
|
|
|
|
}
|
|
|
|
error = p_cansched(curthread, p);
|
|
|
|
if (error) {
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
if (td == NULL)
|
|
|
|
td = FIRST_THREAD_IN_PROC(p);
|
|
|
|
*pp = p;
|
|
|
|
*tdp = td;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2023-01-30 16:28:54 +00:00
|
|
|
static int
|
|
|
|
cpuset_which2(cpuwhich_t *which, id_t id, struct proc **pp, struct thread **tdp,
|
|
|
|
struct cpuset **setp)
|
|
|
|
{
|
|
|
|
|
|
|
|
if (*which == CPU_WHICH_TIDPID) {
|
|
|
|
if (id == -1 || id > PID_MAX)
|
|
|
|
*which = CPU_WHICH_TID;
|
|
|
|
else
|
|
|
|
*which = CPU_WHICH_PID;
|
|
|
|
}
|
|
|
|
return (cpuset_which(*which, id, pp, tdp, setp));
|
|
|
|
}
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
static int
|
|
|
|
cpuset_testshadow(struct cpuset *set, const cpuset_t *mask,
|
|
|
|
const struct domainset *domain)
|
|
|
|
{
|
|
|
|
struct cpuset *parent;
|
|
|
|
struct domainset *dset;
|
|
|
|
|
|
|
|
parent = cpuset_getbase(set);
|
|
|
|
/*
|
|
|
|
* If we are restricting a cpu mask it must be a subset of the
|
|
|
|
* parent or invalid CPUs have been specified.
|
|
|
|
*/
|
|
|
|
if (mask != NULL && !CPU_SUBSET(&parent->cs_mask, mask))
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we are restricting a domain mask it must be a subset of the
|
|
|
|
* parent or invalid domains have been specified.
|
|
|
|
*/
|
|
|
|
dset = parent->cs_domain;
|
|
|
|
if (domain != NULL && !domainset_valid(dset, domain))
|
|
|
|
return (EINVAL);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* Create an anonymous set with the provided mask in the space provided by
|
2018-01-12 22:48:23 +00:00
|
|
|
* 'nset'. If the passed in set is anonymous we use its parent otherwise
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
* the new set is a child of 'set'.
|
|
|
|
*/
|
|
|
|
static int
|
2018-01-12 22:48:23 +00:00
|
|
|
cpuset_shadow(struct cpuset *set, struct cpuset **nsetp,
|
|
|
|
const cpuset_t *mask, const struct domainset *domain,
|
|
|
|
struct setlist *cpusets, struct domainlist *domains)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *parent;
|
2018-01-12 22:48:23 +00:00
|
|
|
struct cpuset *nset;
|
|
|
|
struct domainset *dset;
|
|
|
|
struct domainset *d;
|
|
|
|
int error;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
error = cpuset_testshadow(set, mask, domain);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
parent = cpuset_getbase(set);
|
|
|
|
dset = parent->cs_domain;
|
|
|
|
if (mask == NULL)
|
|
|
|
mask = &set->cs_mask;
|
|
|
|
if (domain != NULL)
|
|
|
|
d = domainset_shadow(dset, domain, domains);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
else
|
2018-01-12 22:48:23 +00:00
|
|
|
d = set->cs_domain;
|
|
|
|
nset = LIST_FIRST(cpusets);
|
2020-11-25 02:12:24 +00:00
|
|
|
error = cpuset_init(nset, parent, mask, d, CPUSET_INVALID);
|
2018-01-12 22:48:23 +00:00
|
|
|
if (error == 0) {
|
|
|
|
LIST_REMOVE(nset, cs_link);
|
|
|
|
*nsetp = nset;
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct cpuset *
|
|
|
|
cpuset_update_thread(struct thread *td, struct cpuset *nset)
|
|
|
|
{
|
|
|
|
struct cpuset *tdset;
|
|
|
|
|
|
|
|
tdset = td->td_cpuset;
|
|
|
|
td->td_cpuset = nset;
|
|
|
|
td->td_domain.dr_policy = nset->cs_domain;
|
|
|
|
sched_affinity(td);
|
|
|
|
|
|
|
|
return (tdset);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuset_setproc_test_maskthread(struct cpuset *tdset, cpuset_t *mask,
|
|
|
|
struct domainset *domain)
|
|
|
|
{
|
|
|
|
struct cpuset *parent;
|
|
|
|
|
|
|
|
parent = cpuset_getbase(tdset);
|
|
|
|
if (mask == NULL)
|
|
|
|
mask = &tdset->cs_mask;
|
|
|
|
if (domain == NULL)
|
|
|
|
domain = tdset->cs_domain;
|
|
|
|
return cpuset_testshadow(parent, mask, domain);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuset_setproc_maskthread(struct cpuset *tdset, cpuset_t *mask,
|
|
|
|
struct domainset *domain, struct cpuset **nsetp,
|
|
|
|
struct setlist *freelist, struct domainlist *domainlist)
|
|
|
|
{
|
|
|
|
struct cpuset *parent;
|
|
|
|
|
|
|
|
parent = cpuset_getbase(tdset);
|
|
|
|
if (mask == NULL)
|
|
|
|
mask = &tdset->cs_mask;
|
|
|
|
if (domain == NULL)
|
|
|
|
domain = tdset->cs_domain;
|
|
|
|
return cpuset_shadow(parent, nsetp, mask, domain, freelist,
|
|
|
|
domainlist);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuset_setproc_setthread_mask(struct cpuset *tdset, struct cpuset *set,
|
|
|
|
cpuset_t *mask, struct domainset *domain)
|
|
|
|
{
|
|
|
|
struct cpuset *parent;
|
|
|
|
|
|
|
|
parent = cpuset_getbase(tdset);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the thread restricted its mask then apply that same
|
|
|
|
* restriction to the new set, otherwise take it wholesale.
|
|
|
|
*/
|
|
|
|
if (CPU_CMP(&tdset->cs_mask, &parent->cs_mask) != 0) {
|
Make CPU_SET macros compliant with other implementations
The introduction of <sched.h> improved compatibility with some 3rd
party software, but caused the configure scripts of some ports to
assume that they were run in a GLIBC compatible environment.
Parts of sched.h were made conditional on -D_WITH_CPU_SET_T being
added to ports, but there still were compatibility issues due to
invalid assumptions made in autoconfigure scripts.
The differences between the FreeBSD version of macros like CPU_AND,
CPU_OR, etc. and the GLIBC versions was in the number of arguments:
FreeBSD used a 2-address scheme (one source argument is also used as
the destination of the operation), while GLIBC uses a 3-adderess
scheme (2 source operands and a separately passed destination).
The GLIBC scheme provides a super-set of the functionality of the
FreeBSD macros, since it does not prevent passing the same variable
as source and destination arguments. In code that wanted to preserve
both source arguments, the FreeBSD macros required a temporary copy of
one of the source arguments.
This patch set allows to unconditionally provide functions and macros
expected by 3rd party software written for GLIBC based systems, but
breaks builds of externally maintained sources that use any of the
following macros: CPU_AND, CPU_ANDNOT, CPU_OR, CPU_XOR.
One contributed driver (contrib/ofed/libmlx5) has been patched to
support both the old and the new CPU_OR signatures. If this commit
is merged to -STABLE, the version test will have to be extended to
cover more ranges.
Ports that have added -D_WITH_CPU_SET_T to build on -CURRENT do
no longer require that option.
The FreeBSD version has been bumped to 1400046 to reflect this
incompatible change.
Reviewed by: kib
MFC after: 2 weeks
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D33451
2021-12-30 11:20:32 +00:00
|
|
|
CPU_AND(mask, &tdset->cs_mask, &set->cs_mask);
|
2018-01-12 22:48:23 +00:00
|
|
|
} else
|
|
|
|
CPU_COPY(&set->cs_mask, mask);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If the thread restricted the domain then we apply the
|
|
|
|
* restriction to the new set but retain the policy.
|
|
|
|
*/
|
|
|
|
if (tdset->cs_domain != parent->cs_domain) {
|
|
|
|
domainset_copy(tdset->cs_domain, domain);
|
|
|
|
DOMAINSET_AND(&domain->ds_mask, &set->cs_domain->ds_mask);
|
|
|
|
} else
|
|
|
|
domainset_copy(set->cs_domain, domain);
|
|
|
|
|
|
|
|
if (CPU_EMPTY(mask) || DOMAINSET_EMPTY(&domain->ds_mask))
|
2008-03-30 11:31:14 +00:00
|
|
|
return (EDEADLK);
|
2018-01-12 22:48:23 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuset_setproc_test_setthread(struct cpuset *tdset, struct cpuset *set)
|
|
|
|
{
|
|
|
|
struct domainset domain;
|
|
|
|
cpuset_t mask;
|
|
|
|
|
|
|
|
if (tdset->cs_id != CPUSET_INVALID)
|
|
|
|
return (0);
|
|
|
|
return cpuset_setproc_setthread_mask(tdset, set, &mask, &domain);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuset_setproc_setthread(struct cpuset *tdset, struct cpuset *set,
|
|
|
|
struct cpuset **nsetp, struct setlist *freelist,
|
|
|
|
struct domainlist *domainlist)
|
|
|
|
{
|
|
|
|
struct domainset domain;
|
|
|
|
cpuset_t mask;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're replacing on a thread that has not constrained the
|
|
|
|
* original set we can simply accept the new set.
|
|
|
|
*/
|
|
|
|
if (tdset->cs_id != CPUSET_INVALID) {
|
|
|
|
*nsetp = cpuset_ref(set);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
error = cpuset_setproc_setthread_mask(tdset, set, &mask, &domain);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
2020-11-23 02:49:53 +00:00
|
|
|
return cpuset_shadow(set, nsetp, &mask, &domain, freelist,
|
2018-01-12 22:48:23 +00:00
|
|
|
domainlist);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
|
|
|
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
static int
|
|
|
|
cpuset_setproc_newbase(struct thread *td, struct cpuset *set,
|
|
|
|
struct cpuset *nroot, struct cpuset **nsetp,
|
|
|
|
struct setlist *cpusets, struct domainlist *domainlist)
|
|
|
|
{
|
|
|
|
struct domainset ndomain;
|
|
|
|
cpuset_t nmask;
|
|
|
|
struct cpuset *pbase;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
pbase = cpuset_getbase(td->td_cpuset);
|
|
|
|
|
|
|
|
/* Copy process mask, then further apply the new root mask. */
|
Make CPU_SET macros compliant with other implementations
The introduction of <sched.h> improved compatibility with some 3rd
party software, but caused the configure scripts of some ports to
assume that they were run in a GLIBC compatible environment.
Parts of sched.h were made conditional on -D_WITH_CPU_SET_T being
added to ports, but there still were compatibility issues due to
invalid assumptions made in autoconfigure scripts.
The differences between the FreeBSD version of macros like CPU_AND,
CPU_OR, etc. and the GLIBC versions was in the number of arguments:
FreeBSD used a 2-address scheme (one source argument is also used as
the destination of the operation), while GLIBC uses a 3-adderess
scheme (2 source operands and a separately passed destination).
The GLIBC scheme provides a super-set of the functionality of the
FreeBSD macros, since it does not prevent passing the same variable
as source and destination arguments. In code that wanted to preserve
both source arguments, the FreeBSD macros required a temporary copy of
one of the source arguments.
This patch set allows to unconditionally provide functions and macros
expected by 3rd party software written for GLIBC based systems, but
breaks builds of externally maintained sources that use any of the
following macros: CPU_AND, CPU_ANDNOT, CPU_OR, CPU_XOR.
One contributed driver (contrib/ofed/libmlx5) has been patched to
support both the old and the new CPU_OR signatures. If this commit
is merged to -STABLE, the version test will have to be extended to
cover more ranges.
Ports that have added -D_WITH_CPU_SET_T to build on -CURRENT do
no longer require that option.
The FreeBSD version has been bumped to 1400046 to reflect this
incompatible change.
Reviewed by: kib
MFC after: 2 weeks
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D33451
2021-12-30 11:20:32 +00:00
|
|
|
CPU_AND(&nmask, &pbase->cs_mask, &nroot->cs_mask);
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
|
|
|
|
domainset_copy(pbase->cs_domain, &ndomain);
|
|
|
|
DOMAINSET_AND(&ndomain.ds_mask, &set->cs_domain->ds_mask);
|
|
|
|
|
|
|
|
/* Policy is too restrictive, will not work. */
|
|
|
|
if (CPU_EMPTY(&nmask) || DOMAINSET_EMPTY(&ndomain.ds_mask))
|
|
|
|
return (EDEADLK);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Remove pbase from the freelist in advance, it'll be pushed to
|
|
|
|
* cpuset_ids on success. We assume here that cpuset_create() will not
|
|
|
|
* touch pbase on failure, and we just enqueue it back to the freelist
|
|
|
|
* to remain in a consistent state.
|
|
|
|
*/
|
|
|
|
pbase = LIST_FIRST(cpusets);
|
|
|
|
LIST_REMOVE(pbase, cs_link);
|
|
|
|
error = cpuset_create(&pbase, set, &nmask);
|
|
|
|
if (error != 0) {
|
|
|
|
LIST_INSERT_HEAD(cpusets, pbase, cs_link);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Duplicates some work from above... oh well. */
|
|
|
|
pbase->cs_domain = domainset_shadow(set->cs_domain, &ndomain,
|
|
|
|
domainlist);
|
|
|
|
*nsetp = pbase;
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
* Handle four cases for updating an entire process.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
* 1) Set is non-null and the process is not rebasing onto a new root. This
|
|
|
|
* reparents all anonymous sets to the provided set and replaces all
|
|
|
|
* non-anonymous td_cpusets with the provided set.
|
|
|
|
* 2) Set is non-null and the process is rebasing onto a new root. This
|
|
|
|
* creates a new base set if the process previously had its own base set,
|
|
|
|
* then reparents all anonymous sets either to that set or the provided set
|
|
|
|
* if one was not created. Non-anonymous sets are similarly replaced.
|
|
|
|
* 3) Mask is non-null. This replaces or creates anonymous sets for every
|
2018-01-12 22:48:23 +00:00
|
|
|
* thread with the existing base as a parent.
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
* 4) domain is non-null. This creates anonymous sets for every thread
|
2018-01-12 22:48:23 +00:00
|
|
|
* and replaces the domain set.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*
|
|
|
|
* This is overly complicated because we can't allocate while holding a
|
|
|
|
* spinlock and spinlocks must be held while changing and examining thread
|
|
|
|
* state.
|
|
|
|
*/
|
|
|
|
static int
|
2018-01-12 22:48:23 +00:00
|
|
|
cpuset_setproc(pid_t pid, struct cpuset *set, cpuset_t *mask,
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
struct domainset *domain, bool rebase)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct setlist freelist;
|
|
|
|
struct setlist droplist;
|
2018-01-12 22:48:23 +00:00
|
|
|
struct domainlist domainlist;
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
struct cpuset *base, *nset, *nroot, *tdroot;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
struct thread *td;
|
|
|
|
struct proc *p;
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
int needed;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
int nfree;
|
|
|
|
int error;
|
2017-05-24 00:58:30 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* The algorithm requires two passes due to locking considerations.
|
|
|
|
*
|
|
|
|
* 1) Lookup the process and acquire the locks in the required order.
|
|
|
|
* 2) If enough cpusets have not been allocated release the locks and
|
|
|
|
* allocate them. Loop.
|
|
|
|
*/
|
2018-01-12 22:48:23 +00:00
|
|
|
cpuset_freelist_init(&freelist, 1);
|
|
|
|
domainset_freelist_init(&domainlist, 1);
|
|
|
|
nfree = 1;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
LIST_INIT(&droplist);
|
|
|
|
nfree = 0;
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
base = set;
|
|
|
|
nroot = NULL;
|
|
|
|
if (set != NULL)
|
|
|
|
nroot = cpuset_getroot(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
for (;;) {
|
|
|
|
error = cpuset_which(CPU_WHICH_PID, pid, &p, &td, &nset);
|
|
|
|
if (error)
|
|
|
|
goto out;
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
tdroot = cpuset_getroot(td->td_cpuset);
|
|
|
|
needed = p->p_numthreads;
|
|
|
|
if (set != NULL && rebase && tdroot != nroot)
|
|
|
|
needed++;
|
|
|
|
if (nfree >= needed)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
|
|
|
PROC_UNLOCK(p);
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
if (nfree < needed) {
|
|
|
|
cpuset_freelist_add(&freelist, needed - nfree);
|
|
|
|
domainset_freelist_add(&domainlist, needed - nfree);
|
|
|
|
nfree = needed;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
PROC_LOCK_ASSERT(p, MA_OWNED);
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we're changing roots and the root set is what has been specified
|
|
|
|
* as the parent, then we'll check if the process was previously using
|
|
|
|
* the root set and, if it wasn't, create a new base with the process's
|
|
|
|
* mask applied to it.
|
2021-02-26 21:46:47 +00:00
|
|
|
*
|
|
|
|
* If the new root is incompatible with the existing mask, then we allow
|
|
|
|
* the process to take on the new root if and only if they have
|
|
|
|
* privilege to widen their mask anyways. Unprivileged processes get
|
|
|
|
* rejected with EDEADLK.
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
*/
|
|
|
|
if (set != NULL && rebase && nroot != tdroot) {
|
|
|
|
cpusetid_t base_id, root_id;
|
|
|
|
|
|
|
|
root_id = td->td_ucred->cr_prison->pr_cpuset->cs_id;
|
|
|
|
base_id = cpuset_getbase(td->td_cpuset)->cs_id;
|
|
|
|
|
|
|
|
if (base_id != root_id) {
|
|
|
|
error = cpuset_setproc_newbase(td, set, nroot, &base,
|
|
|
|
&freelist, &domainlist);
|
2021-02-26 21:46:47 +00:00
|
|
|
if (error == EDEADLK &&
|
|
|
|
priv_check(td, PRIV_SCHED_CPUSET) == 0)
|
|
|
|
error = 0;
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto unlock_out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* Now that the appropriate locks are held and we have enough cpusets,
|
2018-01-12 22:48:23 +00:00
|
|
|
* make sure the operation will succeed before applying changes. The
|
2008-03-05 01:49:20 +00:00
|
|
|
* proc lock prevents td_cpuset from changing between calls.
|
|
|
|
*/
|
|
|
|
error = 0;
|
|
|
|
FOREACH_THREAD_IN_PROC(p, td) {
|
|
|
|
thread_lock(td);
|
2018-01-12 22:48:23 +00:00
|
|
|
if (set != NULL)
|
|
|
|
error = cpuset_setproc_test_setthread(td->td_cpuset,
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
base);
|
2018-01-12 22:48:23 +00:00
|
|
|
else
|
|
|
|
error = cpuset_setproc_test_maskthread(td->td_cpuset,
|
|
|
|
mask, domain);
|
2008-03-05 01:49:20 +00:00
|
|
|
thread_unlock(td);
|
|
|
|
if (error)
|
|
|
|
goto unlock_out;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Replace each thread's cpuset while using deferred release. We
|
2008-03-19 06:19:01 +00:00
|
|
|
* must do this because the thread lock must be held while operating
|
|
|
|
* on the thread and this limits the type of operations allowed.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*/
|
|
|
|
FOREACH_THREAD_IN_PROC(p, td) {
|
|
|
|
thread_lock(td);
|
2018-01-12 22:48:23 +00:00
|
|
|
if (set != NULL)
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
error = cpuset_setproc_setthread(td->td_cpuset, base,
|
2018-01-12 22:48:23 +00:00
|
|
|
&nset, &freelist, &domainlist);
|
|
|
|
else
|
|
|
|
error = cpuset_setproc_maskthread(td->td_cpuset, mask,
|
|
|
|
domain, &nset, &freelist, &domainlist);
|
|
|
|
if (error) {
|
|
|
|
thread_unlock(td);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
cpuset_rel_defer(&droplist, cpuset_update_thread(td, nset));
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_unlock(td);
|
|
|
|
}
|
2008-03-05 01:49:20 +00:00
|
|
|
unlock_out:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
PROC_UNLOCK(p);
|
|
|
|
out:
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
if (base != NULL && base != set)
|
|
|
|
cpuset_rel(base);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
while ((nset = LIST_FIRST(&droplist)) != NULL)
|
|
|
|
cpuset_rel_complete(nset);
|
2018-01-12 22:48:23 +00:00
|
|
|
cpuset_freelist_free(&freelist);
|
|
|
|
domainset_freelist_free(&domainlist);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2018-03-29 02:54:50 +00:00
|
|
|
static int
|
|
|
|
bitset_strprint(char *buf, size_t bufsiz, const struct bitset *set, int setlen)
|
|
|
|
{
|
|
|
|
size_t bytes;
|
|
|
|
int i, once;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
once = 0;
|
|
|
|
p = buf;
|
|
|
|
for (i = 0; i < __bitset_words(setlen); i++) {
|
|
|
|
if (once != 0) {
|
|
|
|
if (bufsiz < 1)
|
|
|
|
return (0);
|
|
|
|
*p = ',';
|
|
|
|
p++;
|
|
|
|
bufsiz--;
|
|
|
|
} else
|
|
|
|
once = 1;
|
|
|
|
if (bufsiz < sizeof(__STRING(ULONG_MAX)))
|
|
|
|
return (0);
|
|
|
|
bytes = snprintf(p, bufsiz, "%lx", set->__bits[i]);
|
|
|
|
p += bytes;
|
|
|
|
bufsiz -= bytes;
|
|
|
|
}
|
|
|
|
return (p - buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
bitset_strscan(struct bitset *set, int setlen, const char *buf)
|
|
|
|
{
|
|
|
|
int i, ret;
|
|
|
|
const char *p;
|
|
|
|
|
|
|
|
BIT_ZERO(setlen, set);
|
|
|
|
p = buf;
|
|
|
|
for (i = 0; i < __bitset_words(setlen); i++) {
|
|
|
|
if (*p == ',') {
|
|
|
|
p++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
ret = sscanf(p, "%lx", &set->__bits[i]);
|
|
|
|
if (ret == 0 || ret == -1)
|
|
|
|
break;
|
|
|
|
while (isxdigit(*p))
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
return (p - buf);
|
|
|
|
}
|
|
|
|
|
Commit the support for removing cpumask_t and replacing it directly with
cpuset_t objects.
That is going to offer the underlying support for a simple bump of
MAXCPU and then support for number of cpus > 32 (as it is today).
Right now, cpumask_t is an int, 32 bits on all our supported architecture.
cpumask_t on the other side is implemented as an array of longs, and
easilly extendible by definition.
The architectures touched by this commit are the following:
- amd64
- i386
- pc98
- arm
- ia64
- XEN
while the others are still missing.
Userland is believed to be fully converted with the changes contained
here.
Some technical notes:
- This commit may be considered an ABI nop for all the architectures
different from amd64 and ia64 (and sparc64 in the future)
- per-cpu members, which are now converted to cpuset_t, needs to be
accessed avoiding migration, because the size of cpuset_t should be
considered unknown
- size of cpuset_t objects is different from kernel and userland (this is
primirally done in order to leave some more space in userland to cope
with KBI extensions). If you need to access kernel cpuset_t from the
userland please refer to example in this patch on how to do that
correctly (kgdb may be a good source, for example).
- Support for other architectures is going to be added soon
- Only MAXCPU for amd64 is bumped now
The patch has been tested by sbruno and Nicholas Esborn on opteron
4 x 12 pack CPUs. More testing on big SMP is expected to came soon.
pluknet tested the patch with his 8-ways on both amd64 and i386.
Tested by: pluknet, sbruno, gianni, Nicholas Esborn
Reviewed by: jeff, jhb, sbruno
2011-05-05 14:39:14 +00:00
|
|
|
/*
|
|
|
|
* Return a string representing a valid layout for a cpuset_t object.
|
|
|
|
* It expects an incoming buffer at least sized as CPUSETBUFSIZ.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
cpusetobj_strprint(char *buf, const cpuset_t *set)
|
|
|
|
{
|
|
|
|
|
2018-03-29 02:54:50 +00:00
|
|
|
bitset_strprint(buf, CPUSETBUFSIZ, (const struct bitset *)set,
|
|
|
|
CPU_SETSIZE);
|
Commit the support for removing cpumask_t and replacing it directly with
cpuset_t objects.
That is going to offer the underlying support for a simple bump of
MAXCPU and then support for number of cpus > 32 (as it is today).
Right now, cpumask_t is an int, 32 bits on all our supported architecture.
cpumask_t on the other side is implemented as an array of longs, and
easilly extendible by definition.
The architectures touched by this commit are the following:
- amd64
- i386
- pc98
- arm
- ia64
- XEN
while the others are still missing.
Userland is believed to be fully converted with the changes contained
here.
Some technical notes:
- This commit may be considered an ABI nop for all the architectures
different from amd64 and ia64 (and sparc64 in the future)
- per-cpu members, which are now converted to cpuset_t, needs to be
accessed avoiding migration, because the size of cpuset_t should be
considered unknown
- size of cpuset_t objects is different from kernel and userland (this is
primirally done in order to leave some more space in userland to cope
with KBI extensions). If you need to access kernel cpuset_t from the
userland please refer to example in this patch on how to do that
correctly (kgdb may be a good source, for example).
- Support for other architectures is going to be added soon
- Only MAXCPU for amd64 is bumped now
The patch has been tested by sbruno and Nicholas Esborn on opteron
4 x 12 pack CPUs. More testing on big SMP is expected to came soon.
pluknet tested the patch with his 8-ways on both amd64 and i386.
Tested by: pluknet, sbruno, gianni, Nicholas Esborn
Reviewed by: jeff, jhb, sbruno
2011-05-05 14:39:14 +00:00
|
|
|
return (buf);
|
|
|
|
}
|
|
|
|
|
2011-05-31 20:48:58 +00:00
|
|
|
/*
|
|
|
|
* Build a valid cpuset_t object from a string representation.
|
|
|
|
* It expects an incoming buffer at least sized as CPUSETBUFSIZ.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
cpusetobj_strscan(cpuset_t *set, const char *buf)
|
|
|
|
{
|
2018-03-29 02:54:50 +00:00
|
|
|
char p;
|
2011-05-31 20:48:58 +00:00
|
|
|
|
|
|
|
if (strlen(buf) > CPUSETBUFSIZ - 1)
|
|
|
|
return (-1);
|
|
|
|
|
2018-03-29 02:54:50 +00:00
|
|
|
p = buf[bitset_strscan((struct bitset *)set, CPU_SETSIZE, buf)];
|
|
|
|
if (p != '\0')
|
2011-05-31 20:48:58 +00:00
|
|
|
return (-1);
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2018-03-29 02:54:50 +00:00
|
|
|
/*
|
|
|
|
* Handle a domainset specifier in the sysctl tree. A poiner to a pointer to
|
|
|
|
* a domainset is in arg1. If the user specifies a valid domainset the
|
|
|
|
* pointer is updated.
|
|
|
|
*
|
|
|
|
* Format is:
|
|
|
|
* hex mask word 0,hex mask word 1,...:decimal policy:decimal preferred
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
sysctl_handle_domainset(SYSCTL_HANDLER_ARGS)
|
|
|
|
{
|
|
|
|
char buf[DOMAINSETBUFSIZ];
|
|
|
|
struct domainset *dset;
|
|
|
|
struct domainset key;
|
|
|
|
int policy, prefer, error;
|
|
|
|
char *p;
|
|
|
|
|
|
|
|
dset = *(struct domainset **)arg1;
|
|
|
|
error = 0;
|
|
|
|
|
|
|
|
if (dset != NULL) {
|
|
|
|
p = buf + bitset_strprint(buf, DOMAINSETBUFSIZ,
|
|
|
|
(const struct bitset *)&dset->ds_mask, DOMAINSET_SETSIZE);
|
|
|
|
sprintf(p, ":%d:%d", dset->ds_policy, dset->ds_prefer);
|
|
|
|
} else
|
|
|
|
sprintf(buf, "<NULL>");
|
|
|
|
error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
|
|
|
|
if (error != 0 || req->newptr == NULL)
|
|
|
|
return (error);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Read in and validate the string.
|
|
|
|
*/
|
|
|
|
memset(&key, 0, sizeof(key));
|
|
|
|
p = &buf[bitset_strscan((struct bitset *)&key.ds_mask,
|
|
|
|
DOMAINSET_SETSIZE, buf)];
|
|
|
|
if (p == buf)
|
|
|
|
return (EINVAL);
|
|
|
|
if (sscanf(p, ":%d:%d", &policy, &prefer) != 2)
|
|
|
|
return (EINVAL);
|
|
|
|
key.ds_policy = policy;
|
|
|
|
key.ds_prefer = prefer;
|
|
|
|
|
|
|
|
/* Domainset_create() validates the policy.*/
|
|
|
|
dset = domainset_create(&key);
|
|
|
|
if (dset == NULL)
|
|
|
|
return (EINVAL);
|
|
|
|
*(struct domainset **)arg1 = dset;
|
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
2018-01-12 22:48:23 +00:00
|
|
|
* Apply an anonymous mask or a domain to a single thread.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*/
|
2018-01-12 22:48:23 +00:00
|
|
|
static int
|
|
|
|
_cpuset_setthread(lwpid_t id, cpuset_t *mask, struct domainset *domain)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
2018-01-12 22:48:23 +00:00
|
|
|
struct setlist cpusets;
|
|
|
|
struct domainlist domainlist;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
struct cpuset *nset;
|
|
|
|
struct cpuset *set;
|
|
|
|
struct thread *td;
|
|
|
|
struct proc *p;
|
|
|
|
int error;
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
cpuset_freelist_init(&cpusets, 1);
|
|
|
|
domainset_freelist_init(&domainlist, domain != NULL);
|
2008-03-05 08:08:32 +00:00
|
|
|
error = cpuset_which(CPU_WHICH_TID, id, &p, &td, &set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
2008-03-30 11:31:14 +00:00
|
|
|
set = NULL;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_lock(td);
|
2018-01-12 22:48:23 +00:00
|
|
|
error = cpuset_shadow(td->td_cpuset, &nset, mask, domain,
|
|
|
|
&cpusets, &domainlist);
|
|
|
|
if (error == 0)
|
|
|
|
set = cpuset_update_thread(td, nset);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_unlock(td);
|
|
|
|
PROC_UNLOCK(p);
|
2008-03-30 11:31:14 +00:00
|
|
|
if (set)
|
|
|
|
cpuset_rel(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
out:
|
2018-01-12 22:48:23 +00:00
|
|
|
cpuset_freelist_free(&cpusets);
|
|
|
|
domainset_freelist_free(&domainlist);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
/*
|
|
|
|
* Apply an anonymous mask to a single thread.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
cpuset_setthread(lwpid_t id, cpuset_t *mask)
|
|
|
|
{
|
|
|
|
|
|
|
|
return _cpuset_setthread(id, mask, NULL);
|
|
|
|
}
|
|
|
|
|
2014-06-22 11:32:23 +00:00
|
|
|
/*
|
|
|
|
* Apply new cpumask to the ithread.
|
|
|
|
*/
|
|
|
|
int
|
2014-09-16 01:21:47 +00:00
|
|
|
cpuset_setithread(lwpid_t id, int cpu)
|
2014-06-22 11:32:23 +00:00
|
|
|
{
|
|
|
|
cpuset_t mask;
|
|
|
|
|
|
|
|
CPU_ZERO(&mask);
|
|
|
|
if (cpu == NOCPU)
|
|
|
|
CPU_COPY(cpuset_root, &mask);
|
|
|
|
else
|
|
|
|
CPU_SET(cpu, &mask);
|
2018-03-29 02:54:50 +00:00
|
|
|
return _cpuset_setthread(id, &mask, NULL);
|
2014-06-22 11:32:23 +00:00
|
|
|
}
|
|
|
|
|
2018-10-20 17:36:00 +00:00
|
|
|
/*
|
|
|
|
* Initialize static domainsets after NUMA information is available. This is
|
2018-10-30 17:57:40 +00:00
|
|
|
* called before memory allocators are initialized.
|
2018-10-20 17:36:00 +00:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
domainset_init(void)
|
|
|
|
{
|
|
|
|
struct domainset *dset;
|
|
|
|
int i;
|
|
|
|
|
2021-04-14 16:56:39 +00:00
|
|
|
dset = &domainset_firsttouch;
|
|
|
|
DOMAINSET_COPY(&all_domains, &dset->ds_mask);
|
|
|
|
dset->ds_policy = DOMAINSET_POLICY_FIRSTTOUCH;
|
|
|
|
dset->ds_prefer = -1;
|
|
|
|
_domainset_create(dset, NULL);
|
|
|
|
|
|
|
|
dset = &domainset_interleave;
|
|
|
|
DOMAINSET_COPY(&all_domains, &dset->ds_mask);
|
|
|
|
dset->ds_policy = DOMAINSET_POLICY_INTERLEAVE;
|
|
|
|
dset->ds_prefer = -1;
|
|
|
|
_domainset_create(dset, NULL);
|
|
|
|
|
2018-10-20 17:36:00 +00:00
|
|
|
dset = &domainset_roundrobin;
|
|
|
|
DOMAINSET_COPY(&all_domains, &dset->ds_mask);
|
|
|
|
dset->ds_policy = DOMAINSET_POLICY_ROUNDROBIN;
|
|
|
|
dset->ds_prefer = -1;
|
|
|
|
_domainset_create(dset, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < vm_ndomains; i++) {
|
2018-10-30 18:26:34 +00:00
|
|
|
dset = &domainset_fixed[i];
|
|
|
|
DOMAINSET_ZERO(&dset->ds_mask);
|
|
|
|
DOMAINSET_SET(i, &dset->ds_mask);
|
|
|
|
dset->ds_policy = DOMAINSET_POLICY_ROUNDROBIN;
|
|
|
|
_domainset_create(dset, NULL);
|
|
|
|
|
2018-10-20 17:36:00 +00:00
|
|
|
dset = &domainset_prefer[i];
|
|
|
|
DOMAINSET_COPY(&all_domains, &dset->ds_mask);
|
|
|
|
dset->ds_policy = DOMAINSET_POLICY_PREFER;
|
|
|
|
dset->ds_prefer = i;
|
|
|
|
_domainset_create(dset, NULL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-29 02:54:50 +00:00
|
|
|
/*
|
2021-04-14 16:56:39 +00:00
|
|
|
* Define the domainsets for cpuset 0, 1 and cpuset 2.
|
2018-03-29 02:54:50 +00:00
|
|
|
*/
|
2018-01-12 22:48:23 +00:00
|
|
|
void
|
|
|
|
domainset_zero(void)
|
|
|
|
{
|
2018-10-30 17:57:40 +00:00
|
|
|
struct domainset *dset, *tmp;
|
2018-01-12 22:48:23 +00:00
|
|
|
|
|
|
|
mtx_init(&cpuset_lock, "cpuset", NULL, MTX_SPIN | MTX_RECURSE);
|
|
|
|
|
2021-04-14 16:56:39 +00:00
|
|
|
domainset0 = &domainset_firsttouch;
|
|
|
|
curthread->td_domain.dr_policy = domainset0;
|
2018-03-29 02:54:50 +00:00
|
|
|
|
2021-04-14 16:56:39 +00:00
|
|
|
domainset2 = &domainset_interleave;
|
|
|
|
kernel_object->domain.dr_policy = domainset2;
|
2018-10-20 17:36:00 +00:00
|
|
|
|
|
|
|
/* Remove empty domains from the global policies. */
|
2018-10-30 17:57:40 +00:00
|
|
|
LIST_FOREACH_SAFE(dset, &cpuset_domains, ds_link, tmp)
|
|
|
|
if (domainset_empty_vm(dset))
|
|
|
|
LIST_REMOVE(dset, ds_link);
|
2018-01-12 22:48:23 +00:00
|
|
|
}
|
2014-06-22 11:32:23 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
2018-03-29 02:54:50 +00:00
|
|
|
* Creates system-wide cpusets and the cpuset for thread0 including three
|
2015-01-08 15:53:13 +00:00
|
|
|
* sets:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*
|
|
|
|
* 0 - The root set which should represent all valid processors in the
|
2020-11-25 02:12:24 +00:00
|
|
|
* system. This set is immutable.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
* 1 - The default set which all processes are a member of until changed.
|
|
|
|
* This allows an administrator to move all threads off of given cpus to
|
|
|
|
* dedicate them to high priority tasks or save power etc.
|
2018-03-29 02:54:50 +00:00
|
|
|
* 2 - The kernel set which allows restriction and policy to be applied only
|
|
|
|
* to kernel threads and the kernel_object.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*/
|
|
|
|
struct cpuset *
|
|
|
|
cpuset_thread0(void)
|
|
|
|
{
|
|
|
|
struct cpuset *set;
|
2018-03-28 18:47:35 +00:00
|
|
|
int i;
|
2018-05-19 05:07:31 +00:00
|
|
|
int error __unused;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
|
|
|
cpuset_zone = uma_zcreate("cpuset", sizeof(struct cpuset), NULL, NULL,
|
2018-03-29 02:54:50 +00:00
|
|
|
NULL, NULL, UMA_ALIGN_CACHE, 0);
|
2018-01-12 22:48:23 +00:00
|
|
|
domainset_zone = uma_zcreate("domainset", sizeof(struct domainset),
|
2018-03-29 02:54:50 +00:00
|
|
|
NULL, NULL, NULL, NULL, UMA_ALIGN_CACHE, 0);
|
2014-06-22 11:32:23 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
2018-03-29 02:54:50 +00:00
|
|
|
* Create the root system set (0) for the whole machine. Doesn't use
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
* cpuset_create() due to NULL parent.
|
|
|
|
*/
|
|
|
|
set = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
|
2018-03-28 18:47:35 +00:00
|
|
|
CPU_COPY(&all_cpus, &set->cs_mask);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
LIST_INIT(&set->cs_children);
|
|
|
|
LIST_INSERT_HEAD(&cpuset_ids, set, cs_link);
|
2020-11-17 00:04:05 +00:00
|
|
|
refcount_init(&set->cs_ref, 1);
|
2018-03-28 18:47:35 +00:00
|
|
|
set->cs_flags = CPU_SET_ROOT | CPU_SET_RDONLY;
|
2021-04-14 16:56:39 +00:00
|
|
|
set->cs_domain = domainset0;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
cpuset_zero = set;
|
2008-03-30 11:31:14 +00:00
|
|
|
cpuset_root = &set->cs_mask;
|
2014-06-22 11:32:23 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
2018-03-29 02:54:50 +00:00
|
|
|
* Now derive a default (1), modifiable set from that to give out.
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
*/
|
2018-01-12 22:48:23 +00:00
|
|
|
set = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
|
2020-11-25 02:12:24 +00:00
|
|
|
error = cpuset_init(set, cpuset_zero, NULL, NULL, 1);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
KASSERT(error == 0, ("Error creating default set: %d\n", error));
|
2014-06-22 11:32:23 +00:00
|
|
|
cpuset_default = set;
|
2018-03-29 02:54:50 +00:00
|
|
|
/*
|
|
|
|
* Create the kernel set (2).
|
|
|
|
*/
|
|
|
|
set = uma_zalloc(cpuset_zone, M_WAITOK | M_ZERO);
|
2020-11-25 02:12:24 +00:00
|
|
|
error = cpuset_init(set, cpuset_zero, NULL, NULL, 2);
|
2018-03-29 02:54:50 +00:00
|
|
|
KASSERT(error == 0, ("Error creating kernel set: %d\n", error));
|
2021-04-14 16:56:39 +00:00
|
|
|
set->cs_domain = domainset2;
|
2018-03-29 02:54:50 +00:00
|
|
|
cpuset_kernel = set;
|
2014-06-22 11:32:23 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
/*
|
|
|
|
* Initialize the unit allocator. 0 and 1 are allocated above.
|
|
|
|
*/
|
2019-09-05 17:48:39 +00:00
|
|
|
cpuset_unr = new_unrhdr(3, INT_MAX, NULL);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
2018-03-28 18:47:35 +00:00
|
|
|
/*
|
|
|
|
* If MD code has not initialized per-domain cpusets, place all
|
|
|
|
* CPUs in domain 0.
|
|
|
|
*/
|
|
|
|
for (i = 0; i < MAXMEMDOM; i++)
|
|
|
|
if (!CPU_EMPTY(&cpuset_domain[i]))
|
|
|
|
goto domains_set;
|
|
|
|
CPU_COPY(&all_cpus, &cpuset_domain[0]);
|
|
|
|
domains_set:
|
|
|
|
|
2018-03-29 02:54:50 +00:00
|
|
|
return (cpuset_default);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
cpuset_kernthread(struct thread *td)
|
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
|
|
|
|
thread_lock(td);
|
|
|
|
set = td->td_cpuset;
|
|
|
|
td->td_cpuset = cpuset_ref(cpuset_kernel);
|
|
|
|
thread_unlock(td);
|
|
|
|
cpuset_rel(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
|
|
|
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
/*
|
|
|
|
* Create a cpuset, which would be cpuset_create() but
|
|
|
|
* mark the new 'set' as root.
|
|
|
|
*
|
2009-04-22 20:49:54 +00:00
|
|
|
* We are not going to reparent the td to it. Use cpuset_setproc_update_set()
|
|
|
|
* for that.
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
*
|
|
|
|
* In case of no error, returns the set in *setp locked with a reference.
|
|
|
|
*/
|
|
|
|
int
|
2009-05-27 14:11:23 +00:00
|
|
|
cpuset_create_root(struct prison *pr, struct cpuset **setp)
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
int error;
|
|
|
|
|
2009-05-27 14:11:23 +00:00
|
|
|
KASSERT(pr != NULL, ("[%s:%d] invalid pr", __func__, __LINE__));
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
KASSERT(setp != NULL, ("[%s:%d] invalid setp", __func__, __LINE__));
|
|
|
|
|
2020-11-25 01:42:32 +00:00
|
|
|
set = NULL;
|
|
|
|
error = cpuset_create(&set, pr->pr_cpuset, &pr->pr_cpuset->cs_mask);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
|
2020-11-25 01:42:32 +00:00
|
|
|
KASSERT(set != NULL, ("[%s:%d] cpuset_create returned invalid data",
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
__func__, __LINE__));
|
|
|
|
|
|
|
|
/* Mark the set as root. */
|
|
|
|
set->cs_flags |= CPU_SET_ROOT;
|
2020-11-25 01:42:32 +00:00
|
|
|
*setp = set;
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
cpuset_setproc_update_set(struct proc *p, struct cpuset *set)
|
|
|
|
{
|
|
|
|
int error;
|
|
|
|
|
|
|
|
KASSERT(p != NULL, ("[%s:%d] invalid proc", __func__, __LINE__));
|
|
|
|
KASSERT(set != NULL, ("[%s:%d] invalid set", __func__, __LINE__));
|
|
|
|
|
|
|
|
cpuset_ref(set);
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
error = cpuset_setproc(p->p_pid, set, NULL, NULL, true);
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
|
|
|
cpuset_rel(set);
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2020-07-06 16:33:21 +00:00
|
|
|
/*
|
|
|
|
* In Capability mode, the only accesses that are permitted are to the current
|
|
|
|
* thread and process' CPU and domain sets.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
cpuset_check_capabilities(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
|
|
|
id_t id)
|
|
|
|
{
|
|
|
|
if (IN_CAPABILITY_MODE(td)) {
|
|
|
|
if (level != CPU_LEVEL_WHICH)
|
|
|
|
return (ECAPMODE);
|
2023-01-29 13:17:33 +00:00
|
|
|
if (which != CPU_WHICH_TID && which != CPU_WHICH_PID &&
|
|
|
|
which != CPU_WHICH_TIDPID)
|
|
|
|
return (ECAPMODE);
|
|
|
|
if (id != -1 && which == CPU_WHICH_TIDPID &&
|
|
|
|
id != td->td_tid && id != td->td_proc->p_pid)
|
2020-07-06 16:33:21 +00:00
|
|
|
return (ECAPMODE);
|
2020-07-06 16:34:09 +00:00
|
|
|
if (id != -1 &&
|
|
|
|
!(which == CPU_WHICH_TID && id == td->td_tid) &&
|
|
|
|
!(which == CPU_WHICH_PID && id == td->td_proc->p_pid))
|
2020-07-06 16:33:21 +00:00
|
|
|
return (ECAPMODE);
|
|
|
|
}
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2022-10-03 14:51:05 +00:00
|
|
|
#if defined(__powerpc__)
|
|
|
|
/*
|
|
|
|
* TODO: At least powerpc64 and powerpc64le kernels panic with
|
|
|
|
* exception 0x480 (instruction segment exception) when copyin/copyout,
|
|
|
|
* are set as a function pointer in cpuset_copy_cb struct and called by
|
|
|
|
* an external module (like pfsync). Tip: copyin/copyout have an ifunc
|
|
|
|
* resolver function.
|
|
|
|
*
|
|
|
|
* Bisect of LLVM shows that the behavior changed on LLVM 10.0 with
|
|
|
|
* https://reviews.llvm.org/rGdc06b0bc9ad055d06535462d91bfc2a744b2f589
|
|
|
|
*
|
|
|
|
* This is a hack/workaround while problem is being discussed with LLVM
|
|
|
|
* community
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
cpuset_copyin(const void *uaddr, void *kaddr, size_t len)
|
|
|
|
{
|
|
|
|
return(copyin(uaddr, kaddr, len));
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
cpuset_copyout(const void *kaddr, void *uaddr, size_t len)
|
|
|
|
{
|
|
|
|
return(copyout(kaddr, uaddr, len));
|
|
|
|
}
|
|
|
|
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
static const struct cpuset_copy_cb copy_set = {
|
2022-10-03 14:51:05 +00:00
|
|
|
.cpuset_copyin = cpuset_copyin,
|
|
|
|
.cpuset_copyout = cpuset_copyout
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
};
|
2022-10-03 14:51:05 +00:00
|
|
|
#else
|
|
|
|
static const struct cpuset_copy_cb copy_set = {
|
|
|
|
.cpuset_copyin = copyin,
|
|
|
|
.cpuset_copyout = copyout
|
|
|
|
};
|
|
|
|
#endif
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct cpuset_args {
|
|
|
|
cpusetid_t *setid;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_cpuset(struct thread *td, struct cpuset_args *uap)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *root;
|
|
|
|
struct cpuset *set;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
thread_lock(td);
|
2008-03-30 11:31:14 +00:00
|
|
|
root = cpuset_refroot(td->td_cpuset);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_unlock(td);
|
2020-11-25 01:42:32 +00:00
|
|
|
set = NULL;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
error = cpuset_create(&set, root, &root->cs_mask);
|
|
|
|
cpuset_rel(root);
|
|
|
|
if (error)
|
|
|
|
return (error);
|
2008-03-30 11:31:14 +00:00
|
|
|
error = copyout(&set->cs_id, uap->setid, sizeof(set->cs_id));
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error == 0)
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
error = cpuset_setproc(-1, set, NULL, NULL, false);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
cpuset_rel(set);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct cpuset_setid_args {
|
|
|
|
cpuwhich_t which;
|
|
|
|
id_t id;
|
|
|
|
cpusetid_t setid;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_cpuset_setid(struct thread *td, struct cpuset_setid_args *uap)
|
2017-01-31 15:11:23 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_cpuset_setid(td, uap->which, uap->id, uap->setid));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_cpuset_setid(struct thread *td, cpuwhich_t which,
|
|
|
|
id_t id, cpusetid_t setid)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Presently we only support per-process sets.
|
|
|
|
*/
|
2017-01-31 15:11:23 +00:00
|
|
|
if (which != CPU_WHICH_PID)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
return (EINVAL);
|
2017-01-31 15:11:23 +00:00
|
|
|
set = cpuset_lookup(setid, td);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (set == NULL)
|
|
|
|
return (ESRCH);
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
error = cpuset_setproc(id, set, NULL, NULL, false);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
cpuset_rel(set);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct cpuset_getid_args {
|
|
|
|
cpulevel_t level;
|
|
|
|
cpuwhich_t which;
|
|
|
|
id_t id;
|
|
|
|
cpusetid_t *setid;
|
2011-12-05 10:34:52 +00:00
|
|
|
};
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_cpuset_getid(struct thread *td, struct cpuset_getid_args *uap)
|
2017-01-31 15:11:23 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_cpuset_getid(td, uap->level, uap->which, uap->id,
|
|
|
|
uap->setid));
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_cpuset_getid(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
|
|
|
id_t id, cpusetid_t *setid)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *nset;
|
|
|
|
struct cpuset *set;
|
|
|
|
struct thread *ttd;
|
|
|
|
struct proc *p;
|
2017-01-31 15:11:23 +00:00
|
|
|
cpusetid_t tmpid;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
int error;
|
|
|
|
|
2017-01-31 15:11:23 +00:00
|
|
|
if (level == CPU_LEVEL_WHICH && which != CPU_WHICH_CPUSET)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
return (EINVAL);
|
2017-01-31 15:11:23 +00:00
|
|
|
error = cpuset_which(which, id, &p, &ttd, &set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error)
|
|
|
|
return (error);
|
2017-01-31 15:11:23 +00:00
|
|
|
switch (which) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_WHICH_TID:
|
|
|
|
case CPU_WHICH_PID:
|
2023-01-30 16:28:54 +00:00
|
|
|
case CPU_WHICH_TIDPID:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_lock(ttd);
|
2008-03-30 11:31:14 +00:00
|
|
|
set = cpuset_refbase(ttd->td_cpuset);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_unlock(ttd);
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_CPUSET:
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
case CPU_WHICH_JAIL:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
2008-04-11 03:26:41 +00:00
|
|
|
case CPU_WHICH_IRQ:
|
2015-01-08 15:53:13 +00:00
|
|
|
case CPU_WHICH_DOMAIN:
|
2008-04-11 03:26:41 +00:00
|
|
|
return (EINVAL);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
2017-01-31 15:11:23 +00:00
|
|
|
switch (level) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_LEVEL_ROOT:
|
2008-03-30 11:31:14 +00:00
|
|
|
nset = cpuset_refroot(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
cpuset_rel(set);
|
|
|
|
set = nset;
|
|
|
|
break;
|
|
|
|
case CPU_LEVEL_CPUSET:
|
|
|
|
break;
|
|
|
|
case CPU_LEVEL_WHICH:
|
|
|
|
break;
|
|
|
|
}
|
2017-01-31 15:11:23 +00:00
|
|
|
tmpid = set->cs_id;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
cpuset_rel(set);
|
|
|
|
if (error == 0)
|
2017-08-22 20:46:29 +00:00
|
|
|
error = copyout(&tmpid, setid, sizeof(tmpid));
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct cpuset_getaffinity_args {
|
2008-03-25 09:11:53 +00:00
|
|
|
cpulevel_t level;
|
|
|
|
cpuwhich_t which;
|
|
|
|
id_t id;
|
|
|
|
size_t cpusetsize;
|
|
|
|
cpuset_t *mask;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_cpuset_getaffinity(struct thread *td, struct cpuset_getaffinity_args *uap)
|
2017-02-05 13:24:54 +00:00
|
|
|
{
|
|
|
|
|
2022-05-28 17:53:08 +00:00
|
|
|
return (user_cpuset_getaffinity(td, uap->level, uap->which,
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
uap->id, uap->cpusetsize, uap->mask, ©_set));
|
2017-02-05 13:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_cpuset_getaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
2022-05-28 17:53:08 +00:00
|
|
|
id_t id, size_t cpusetsize, cpuset_t *mask)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct thread *ttd;
|
|
|
|
struct cpuset *nset;
|
|
|
|
struct cpuset *set;
|
|
|
|
struct proc *p;
|
|
|
|
int error;
|
|
|
|
|
2020-07-06 16:33:21 +00:00
|
|
|
error = cpuset_check_capabilities(td, level, which, id);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2023-01-30 16:28:54 +00:00
|
|
|
error = cpuset_which2(&which, id, &p, &ttd, &set);
|
2022-05-28 17:53:08 +00:00
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2017-02-05 13:24:54 +00:00
|
|
|
switch (level) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_LEVEL_ROOT:
|
|
|
|
case CPU_LEVEL_CPUSET:
|
2017-02-05 13:24:54 +00:00
|
|
|
switch (which) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_WHICH_TID:
|
|
|
|
case CPU_WHICH_PID:
|
|
|
|
thread_lock(ttd);
|
|
|
|
set = cpuset_ref(ttd->td_cpuset);
|
|
|
|
thread_unlock(ttd);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_CPUSET:
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
case CPU_WHICH_JAIL:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
2008-04-11 03:26:41 +00:00
|
|
|
case CPU_WHICH_IRQ:
|
2017-05-03 18:41:08 +00:00
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
2015-01-08 15:53:13 +00:00
|
|
|
case CPU_WHICH_DOMAIN:
|
2022-05-28 17:53:08 +00:00
|
|
|
return (EINVAL);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
2017-02-05 13:24:54 +00:00
|
|
|
if (level == CPU_LEVEL_ROOT)
|
2008-03-30 11:31:14 +00:00
|
|
|
nset = cpuset_refroot(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
else
|
2008-03-30 11:31:14 +00:00
|
|
|
nset = cpuset_refbase(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
CPU_COPY(&nset->cs_mask, mask);
|
|
|
|
cpuset_rel(nset);
|
|
|
|
break;
|
|
|
|
case CPU_LEVEL_WHICH:
|
2017-02-05 13:24:54 +00:00
|
|
|
switch (which) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_WHICH_TID:
|
|
|
|
thread_lock(ttd);
|
|
|
|
CPU_COPY(&ttd->td_cpuset->cs_mask, mask);
|
|
|
|
thread_unlock(ttd);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_PID:
|
|
|
|
FOREACH_THREAD_IN_PROC(p, ttd) {
|
|
|
|
thread_lock(ttd);
|
Make CPU_SET macros compliant with other implementations
The introduction of <sched.h> improved compatibility with some 3rd
party software, but caused the configure scripts of some ports to
assume that they were run in a GLIBC compatible environment.
Parts of sched.h were made conditional on -D_WITH_CPU_SET_T being
added to ports, but there still were compatibility issues due to
invalid assumptions made in autoconfigure scripts.
The differences between the FreeBSD version of macros like CPU_AND,
CPU_OR, etc. and the GLIBC versions was in the number of arguments:
FreeBSD used a 2-address scheme (one source argument is also used as
the destination of the operation), while GLIBC uses a 3-adderess
scheme (2 source operands and a separately passed destination).
The GLIBC scheme provides a super-set of the functionality of the
FreeBSD macros, since it does not prevent passing the same variable
as source and destination arguments. In code that wanted to preserve
both source arguments, the FreeBSD macros required a temporary copy of
one of the source arguments.
This patch set allows to unconditionally provide functions and macros
expected by 3rd party software written for GLIBC based systems, but
breaks builds of externally maintained sources that use any of the
following macros: CPU_AND, CPU_ANDNOT, CPU_OR, CPU_XOR.
One contributed driver (contrib/ofed/libmlx5) has been patched to
support both the old and the new CPU_OR signatures. If this commit
is merged to -STABLE, the version test will have to be extended to
cover more ranges.
Ports that have added -D_WITH_CPU_SET_T to build on -CURRENT do
no longer require that option.
The FreeBSD version has been bumped to 1400046 to reflect this
incompatible change.
Reviewed by: kib
MFC after: 2 weeks
Relnotes: yes
Differential Revision: https://reviews.freebsd.org/D33451
2021-12-30 11:20:32 +00:00
|
|
|
CPU_OR(mask, mask, &ttd->td_cpuset->cs_mask);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_unlock(ttd);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_CPUSET:
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
case CPU_WHICH_JAIL:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
CPU_COPY(&set->cs_mask, mask);
|
|
|
|
break;
|
2008-04-11 03:26:41 +00:00
|
|
|
case CPU_WHICH_IRQ:
|
2017-05-03 18:41:08 +00:00
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
|
|
|
error = intr_getaffinity(id, which, mask);
|
2008-04-11 03:26:41 +00:00
|
|
|
break;
|
2015-01-08 15:53:13 +00:00
|
|
|
case CPU_WHICH_DOMAIN:
|
2017-02-05 13:24:54 +00:00
|
|
|
if (id < 0 || id >= MAXMEMDOM)
|
2015-01-08 15:53:13 +00:00
|
|
|
error = ESRCH;
|
|
|
|
else
|
2017-02-05 13:24:54 +00:00
|
|
|
CPU_COPY(&cpuset_domain[id], mask);
|
2015-01-08 15:53:13 +00:00
|
|
|
break;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (set)
|
|
|
|
cpuset_rel(set);
|
|
|
|
if (p)
|
|
|
|
PROC_UNLOCK(p);
|
2022-05-11 07:36:01 +00:00
|
|
|
if (error == 0) {
|
2022-05-28 17:53:08 +00:00
|
|
|
if (cpusetsize < howmany(CPU_FLS(mask), NBBY))
|
|
|
|
return (ERANGE);
|
|
|
|
#ifdef KTRACE
|
|
|
|
if (KTRPOINT(td, KTR_STRUCT))
|
|
|
|
ktrcpuset(mask, cpusetsize);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
user_cpuset_getaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
|
|
|
id_t id, size_t cpusetsize, cpuset_t *maskp, const struct cpuset_copy_cb *cb)
|
|
|
|
{
|
|
|
|
cpuset_t *mask;
|
|
|
|
size_t size;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
mask = malloc(sizeof(cpuset_t), M_TEMP, M_WAITOK | M_ZERO);
|
|
|
|
size = min(cpusetsize, sizeof(cpuset_t));
|
|
|
|
error = kern_cpuset_getaffinity(td, level, which, id, size, mask);
|
|
|
|
if (error == 0) {
|
2022-05-20 14:11:31 +00:00
|
|
|
error = cb->cpuset_copyout(mask, maskp, size);
|
2022-05-11 07:36:01 +00:00
|
|
|
if (error != 0)
|
|
|
|
goto out;
|
|
|
|
if (cpusetsize > size) {
|
|
|
|
char *end;
|
|
|
|
char *cp;
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
end = cp = (char *)&maskp->__bits;
|
|
|
|
end += cpusetsize;
|
|
|
|
cp += size;
|
|
|
|
while (cp != end) {
|
|
|
|
rv = subyte(cp, 0);
|
|
|
|
if (rv == -1) {
|
|
|
|
error = EFAULT;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
cp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
out:
|
|
|
|
free(mask, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct cpuset_setaffinity_args {
|
|
|
|
cpulevel_t level;
|
2008-03-25 09:11:53 +00:00
|
|
|
cpuwhich_t which;
|
|
|
|
id_t id;
|
|
|
|
size_t cpusetsize;
|
|
|
|
const cpuset_t *mask;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
2011-09-16 13:58:51 +00:00
|
|
|
sys_cpuset_setaffinity(struct thread *td, struct cpuset_setaffinity_args *uap)
|
2017-02-05 13:24:54 +00:00
|
|
|
{
|
|
|
|
|
2022-05-11 07:36:01 +00:00
|
|
|
return (user_cpuset_setaffinity(td, uap->level, uap->which,
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
uap->id, uap->cpusetsize, uap->mask, ©_set));
|
2017-02-05 13:24:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_cpuset_setaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
2022-05-11 07:36:01 +00:00
|
|
|
id_t id, cpuset_t *mask)
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
{
|
|
|
|
struct cpuset *nset;
|
|
|
|
struct cpuset *set;
|
|
|
|
struct thread *ttd;
|
|
|
|
struct proc *p;
|
|
|
|
int error;
|
|
|
|
|
2022-05-11 07:40:39 +00:00
|
|
|
#ifdef KTRACE
|
|
|
|
if (KTRPOINT(td, KTR_STRUCT))
|
|
|
|
ktrcpuset(mask, sizeof(cpuset_t));
|
|
|
|
#endif
|
2020-07-06 16:33:21 +00:00
|
|
|
error = cpuset_check_capabilities(td, level, which, id);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2022-05-11 07:36:01 +00:00
|
|
|
if (CPU_EMPTY(mask))
|
|
|
|
return (EDEADLK);
|
2017-02-05 13:24:54 +00:00
|
|
|
switch (level) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_LEVEL_ROOT:
|
|
|
|
case CPU_LEVEL_CPUSET:
|
2017-02-05 13:24:54 +00:00
|
|
|
error = cpuset_which(which, id, &p, &ttd, &set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error)
|
|
|
|
break;
|
2017-02-05 13:24:54 +00:00
|
|
|
switch (which) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_WHICH_TID:
|
|
|
|
case CPU_WHICH_PID:
|
2023-01-30 16:28:54 +00:00
|
|
|
case CPU_WHICH_TIDPID:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
thread_lock(ttd);
|
|
|
|
set = cpuset_ref(ttd->td_cpuset);
|
|
|
|
thread_unlock(ttd);
|
2008-03-06 20:11:24 +00:00
|
|
|
PROC_UNLOCK(p);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
|
|
|
case CPU_WHICH_CPUSET:
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
case CPU_WHICH_JAIL:
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
2008-04-11 03:26:41 +00:00
|
|
|
case CPU_WHICH_IRQ:
|
2017-05-03 18:41:08 +00:00
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
2015-01-08 15:53:13 +00:00
|
|
|
case CPU_WHICH_DOMAIN:
|
2022-05-11 07:36:01 +00:00
|
|
|
return (EINVAL);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
}
|
2017-02-05 13:24:54 +00:00
|
|
|
if (level == CPU_LEVEL_ROOT)
|
2008-03-30 11:31:14 +00:00
|
|
|
nset = cpuset_refroot(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
else
|
2008-03-30 11:31:14 +00:00
|
|
|
nset = cpuset_refbase(set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
error = cpuset_modify(nset, mask);
|
|
|
|
cpuset_rel(nset);
|
|
|
|
cpuset_rel(set);
|
|
|
|
break;
|
|
|
|
case CPU_LEVEL_WHICH:
|
2017-02-05 13:24:54 +00:00
|
|
|
switch (which) {
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_WHICH_TID:
|
2017-02-05 13:24:54 +00:00
|
|
|
error = cpuset_setthread(id, mask);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
|
|
|
case CPU_WHICH_PID:
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
error = cpuset_setproc(id, NULL, mask, NULL, false);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
break;
|
2023-01-29 13:17:33 +00:00
|
|
|
case CPU_WHICH_TIDPID:
|
|
|
|
if (id > PID_MAX || id == -1)
|
|
|
|
error = cpuset_setthread(id, mask);
|
|
|
|
else
|
|
|
|
error = cpuset_setproc(id, NULL, mask, NULL,
|
|
|
|
false);
|
|
|
|
break;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
case CPU_WHICH_CPUSET:
|
MFp4:
Bring in updated jail support from bz_jail branch.
This enhances the current jail implementation to permit multiple
addresses per jail. In addtion to IPv4, IPv6 is supported as well.
Due to updated checks it is even possible to have jails without
an IP address at all, which basically gives one a chroot with
restricted process view, no networking,..
SCTP support was updated and supports IPv6 in jails as well.
Cpuset support permits jails to be bound to specific processor
sets after creation.
Jails can have an unrestricted (no duplicate protection, etc.) name
in addition to the hostname. The jail name cannot be changed from
within a jail and is considered to be used for management purposes
or as audit-token in the future.
DDB 'show jails' command was added to aid debugging.
Proper compat support permits 32bit jail binaries to be used on 64bit
systems to manage jails. Also backward compatibility was preserved where
possible: for jail v1 syscalls, as well as with user space management
utilities.
Both jail as well as prison version were updated for the new features.
A gap was intentionally left as the intermediate versions had been
used by various patches floating around the last years.
Bump __FreeBSD_version for the afore mentioned and in kernel changes.
Special thanks to:
- Pawel Jakub Dawidek (pjd) for his multi-IPv4 patches
and Olivier Houchard (cognet) for initial single-IPv6 patches.
- Jeff Roberson (jeff) and Randall Stewart (rrs) for their
help, ideas and review on cpuset and SCTP support.
- Robert Watson (rwatson) for lots and lots of help, discussions,
suggestions and review of most of the patch at various stages.
- John Baldwin (jhb) for his help.
- Simon L. Nielsen (simon) as early adopter testing changes
on cluster machines as well as all the testers and people
who provided feedback the last months on freebsd-jail and
other channels.
- My employer, CK Software GmbH, for the support so I could work on this.
Reviewed by: (see above)
MFC after: 3 months (this is just so that I get the mail)
X-MFC Before: 7.2-RELEASE if possible
2008-11-29 14:32:14 +00:00
|
|
|
case CPU_WHICH_JAIL:
|
2017-02-05 13:24:54 +00:00
|
|
|
error = cpuset_which(which, id, &p, &ttd, &set);
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
if (error == 0) {
|
|
|
|
error = cpuset_modify(set, mask);
|
|
|
|
cpuset_rel(set);
|
|
|
|
}
|
|
|
|
break;
|
2008-04-11 03:26:41 +00:00
|
|
|
case CPU_WHICH_IRQ:
|
2017-05-03 18:41:08 +00:00
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
|
|
|
error = intr_setaffinity(id, which, mask);
|
2008-04-11 03:26:41 +00:00
|
|
|
break;
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
2022-05-11 07:36:01 +00:00
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
user_cpuset_setaffinity(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
id_t id, size_t cpusetsize, const cpuset_t *maskp, const struct cpuset_copy_cb *cb)
|
2022-05-11 07:36:01 +00:00
|
|
|
{
|
|
|
|
cpuset_t *mask;
|
|
|
|
int error;
|
|
|
|
size_t size;
|
|
|
|
|
|
|
|
size = min(cpusetsize, sizeof(cpuset_t));
|
|
|
|
mask = malloc(sizeof(cpuset_t), M_TEMP, M_WAITOK | M_ZERO);
|
2022-05-20 14:11:31 +00:00
|
|
|
error = cb->cpuset_copyin(maskp, mask, size);
|
2022-05-11 07:36:01 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
/*
|
|
|
|
* Verify that no high bits are set.
|
|
|
|
*/
|
|
|
|
if (cpusetsize > sizeof(cpuset_t)) {
|
|
|
|
const char *end, *cp;
|
|
|
|
int val;
|
|
|
|
end = cp = (const char *)&maskp->__bits;
|
|
|
|
end += cpusetsize;
|
|
|
|
cp += sizeof(cpuset_t);
|
|
|
|
|
|
|
|
while (cp != end) {
|
|
|
|
val = fubyte(cp);
|
|
|
|
if (val == -1) {
|
|
|
|
error = EFAULT;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (val != 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
cp++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
error = kern_cpuset_setaffinity(td, level, which, id, mask);
|
|
|
|
|
Add cpuset, an api for thread to cpu binding and cpu resource grouping
and assignment.
- Add a reference to a struct cpuset in each thread that is inherited from
the thread that created it.
- Release the reference when the thread is destroyed.
- Add prototypes for syscalls and macros for manipulating cpusets in
sys/cpuset.h
- Add syscalls to create, get, and set new numbered cpusets:
cpuset(), cpuset_{get,set}id()
- Add syscalls for getting and setting affinity masks for cpusets or
individual threads: cpuid_{get,set}affinity()
- Add types for the 'level' and 'which' parameters for the cpuset. This
will permit expansion of the api to cover cpu masks for other objects
identifiable with an id_t integer. For example, IRQs and Jails may be
coming soon.
- The root set 0 contains all valid cpus. All thread initially belong to
cpuset 1. This permits migrating all threads off of certain cpus to
reserve them for special applications.
Sponsored by: Nokia
Discussed with: arch, rwatson, brooks, davidxu, deischen
Reviewed by: antoine
2008-03-02 07:39:22 +00:00
|
|
|
out:
|
|
|
|
free(mask, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
2008-07-07 21:32:02 +00:00
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct cpuset_getdomain_args {
|
|
|
|
cpulevel_t level;
|
|
|
|
cpuwhich_t which;
|
|
|
|
id_t id;
|
|
|
|
size_t domainsetsize;
|
|
|
|
domainset_t *mask;
|
|
|
|
int *policy;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_cpuset_getdomain(struct thread *td, struct cpuset_getdomain_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_cpuset_getdomain(td, uap->level, uap->which,
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
uap->id, uap->domainsetsize, uap->mask, uap->policy, ©_set));
|
2018-01-12 22:48:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_cpuset_getdomain(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
id_t id, size_t domainsetsize, domainset_t *maskp, int *policyp,
|
|
|
|
const struct cpuset_copy_cb *cb)
|
2018-01-12 22:48:23 +00:00
|
|
|
{
|
|
|
|
struct domainset outset;
|
|
|
|
struct thread *ttd;
|
|
|
|
struct cpuset *nset;
|
|
|
|
struct cpuset *set;
|
|
|
|
struct domainset *dset;
|
|
|
|
struct proc *p;
|
|
|
|
domainset_t *mask;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (domainsetsize < sizeof(domainset_t) ||
|
|
|
|
domainsetsize > DOMAINSET_MAXSIZE / NBBY)
|
|
|
|
return (ERANGE);
|
2020-07-06 16:33:21 +00:00
|
|
|
error = cpuset_check_capabilities(td, level, which, id);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2018-01-12 22:48:23 +00:00
|
|
|
mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO);
|
|
|
|
bzero(&outset, sizeof(outset));
|
2023-01-30 16:28:54 +00:00
|
|
|
error = cpuset_which2(&which, id, &p, &ttd, &set);
|
2018-01-12 22:48:23 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
switch (level) {
|
|
|
|
case CPU_LEVEL_ROOT:
|
|
|
|
case CPU_LEVEL_CPUSET:
|
|
|
|
switch (which) {
|
|
|
|
case CPU_WHICH_TID:
|
|
|
|
case CPU_WHICH_PID:
|
|
|
|
thread_lock(ttd);
|
|
|
|
set = cpuset_ref(ttd->td_cpuset);
|
|
|
|
thread_unlock(ttd);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_CPUSET:
|
|
|
|
case CPU_WHICH_JAIL:
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_IRQ:
|
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
|
|
|
case CPU_WHICH_DOMAIN:
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (level == CPU_LEVEL_ROOT)
|
|
|
|
nset = cpuset_refroot(set);
|
|
|
|
else
|
|
|
|
nset = cpuset_refbase(set);
|
|
|
|
domainset_copy(nset->cs_domain, &outset);
|
|
|
|
cpuset_rel(nset);
|
|
|
|
break;
|
|
|
|
case CPU_LEVEL_WHICH:
|
|
|
|
switch (which) {
|
|
|
|
case CPU_WHICH_TID:
|
|
|
|
thread_lock(ttd);
|
|
|
|
domainset_copy(ttd->td_cpuset->cs_domain, &outset);
|
|
|
|
thread_unlock(ttd);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_PID:
|
|
|
|
FOREACH_THREAD_IN_PROC(p, ttd) {
|
|
|
|
thread_lock(ttd);
|
|
|
|
dset = ttd->td_cpuset->cs_domain;
|
|
|
|
/* Show all domains in the proc. */
|
|
|
|
DOMAINSET_OR(&outset.ds_mask, &dset->ds_mask);
|
|
|
|
/* Last policy wins. */
|
|
|
|
outset.ds_policy = dset->ds_policy;
|
|
|
|
outset.ds_prefer = dset->ds_prefer;
|
|
|
|
thread_unlock(ttd);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_CPUSET:
|
|
|
|
case CPU_WHICH_JAIL:
|
|
|
|
domainset_copy(set->cs_domain, &outset);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_IRQ:
|
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
|
|
|
case CPU_WHICH_DOMAIN:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (set)
|
|
|
|
cpuset_rel(set);
|
|
|
|
if (p)
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
/*
|
|
|
|
* Translate prefer into a set containing only the preferred domain,
|
|
|
|
* not the entire fallback set.
|
|
|
|
*/
|
|
|
|
if (outset.ds_policy == DOMAINSET_POLICY_PREFER) {
|
|
|
|
DOMAINSET_ZERO(&outset.ds_mask);
|
|
|
|
DOMAINSET_SET(outset.ds_prefer, &outset.ds_mask);
|
|
|
|
}
|
|
|
|
DOMAINSET_COPY(&outset.ds_mask, mask);
|
|
|
|
if (error == 0)
|
2022-05-20 14:11:31 +00:00
|
|
|
error = cb->cpuset_copyout(mask, maskp, domainsetsize);
|
2018-01-12 22:48:23 +00:00
|
|
|
if (error == 0)
|
2018-03-09 00:50:40 +00:00
|
|
|
if (suword32(policyp, outset.ds_policy) != 0)
|
|
|
|
error = EFAULT;
|
2018-01-12 22:48:23 +00:00
|
|
|
out:
|
|
|
|
free(mask, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifndef _SYS_SYSPROTO_H_
|
|
|
|
struct cpuset_setdomain_args {
|
|
|
|
cpulevel_t level;
|
|
|
|
cpuwhich_t which;
|
|
|
|
id_t id;
|
|
|
|
size_t domainsetsize;
|
|
|
|
domainset_t *mask;
|
|
|
|
int policy;
|
|
|
|
};
|
|
|
|
#endif
|
|
|
|
int
|
|
|
|
sys_cpuset_setdomain(struct thread *td, struct cpuset_setdomain_args *uap)
|
|
|
|
{
|
|
|
|
|
|
|
|
return (kern_cpuset_setdomain(td, uap->level, uap->which,
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
uap->id, uap->domainsetsize, uap->mask, uap->policy, ©_set));
|
2018-01-12 22:48:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
|
|
|
kern_cpuset_setdomain(struct thread *td, cpulevel_t level, cpuwhich_t which,
|
cpuset: Byte swap cpuset for compat32 on big endian architectures
Summary:
BITSET uses long as its basic underlying type, which is dependent on the
compile type, meaning on 32-bit builds the basic type is 32 bits, but on
64-bit builds it's 64 bits. On little endian architectures this doesn't
matter, because the LSB is always at the low bit, so the words get
effectively concatenated moving between 32-bit and 64-bit, but on
big-endian architectures it throws a wrench in, as setting bit 0 in
32-bit mode is equivalent to setting bit 32 in 64-bit mode. To
demonstrate:
32-bit mode:
BIT_SET(foo, 0): 0x00000001
64-bit sees: 0x0000000100000000
cpuset is the only system interface that uses bitsets, so solve this
by swapping the integer sub-components at the copyin/copyout points.
Reviewed by: kib
MFC after: 3 days
Sponsored by: Juniper Networks, Inc.
Differential Revision: https://reviews.freebsd.org/D35225
2022-05-12 20:38:22 +00:00
|
|
|
id_t id, size_t domainsetsize, const domainset_t *maskp, int policy,
|
|
|
|
const struct cpuset_copy_cb *cb)
|
2018-01-12 22:48:23 +00:00
|
|
|
{
|
|
|
|
struct cpuset *nset;
|
|
|
|
struct cpuset *set;
|
|
|
|
struct thread *ttd;
|
|
|
|
struct proc *p;
|
|
|
|
struct domainset domain;
|
|
|
|
domainset_t *mask;
|
|
|
|
int error;
|
|
|
|
|
|
|
|
if (domainsetsize < sizeof(domainset_t) ||
|
|
|
|
domainsetsize > DOMAINSET_MAXSIZE / NBBY)
|
|
|
|
return (ERANGE);
|
2018-05-26 14:23:11 +00:00
|
|
|
if (policy <= DOMAINSET_POLICY_INVALID ||
|
|
|
|
policy > DOMAINSET_POLICY_MAX)
|
|
|
|
return (EINVAL);
|
2020-07-06 16:33:21 +00:00
|
|
|
error = cpuset_check_capabilities(td, level, which, id);
|
|
|
|
if (error != 0)
|
|
|
|
return (error);
|
2018-01-12 22:48:23 +00:00
|
|
|
memset(&domain, 0, sizeof(domain));
|
|
|
|
mask = malloc(domainsetsize, M_TEMP, M_WAITOK | M_ZERO);
|
2022-05-20 14:11:31 +00:00
|
|
|
error = cb->cpuset_copyin(maskp, mask, domainsetsize);
|
2018-01-12 22:48:23 +00:00
|
|
|
if (error)
|
|
|
|
goto out;
|
|
|
|
/*
|
|
|
|
* Verify that no high bits are set.
|
|
|
|
*/
|
|
|
|
if (domainsetsize > sizeof(domainset_t)) {
|
|
|
|
char *end;
|
|
|
|
char *cp;
|
|
|
|
|
|
|
|
end = cp = (char *)&mask->__bits;
|
|
|
|
end += domainsetsize;
|
|
|
|
cp += sizeof(domainset_t);
|
|
|
|
while (cp != end)
|
|
|
|
if (*cp++ != 0) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
2020-12-08 18:47:22 +00:00
|
|
|
if (DOMAINSET_EMPTY(mask)) {
|
|
|
|
error = EDEADLK;
|
|
|
|
goto out;
|
|
|
|
}
|
2018-01-12 22:48:23 +00:00
|
|
|
DOMAINSET_COPY(mask, &domain.ds_mask);
|
|
|
|
domain.ds_policy = policy;
|
|
|
|
|
2019-09-01 21:38:08 +00:00
|
|
|
/*
|
|
|
|
* Sanitize the provided mask.
|
|
|
|
*/
|
|
|
|
if (!DOMAINSET_SUBSET(&all_domains, &domain.ds_mask)) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
/* Translate preferred policy into a mask and fallback. */
|
|
|
|
if (policy == DOMAINSET_POLICY_PREFER) {
|
|
|
|
/* Only support a single preferred domain. */
|
2018-05-26 14:23:11 +00:00
|
|
|
if (DOMAINSET_COUNT(&domain.ds_mask) != 1) {
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
2018-01-12 22:48:23 +00:00
|
|
|
domain.ds_prefer = DOMAINSET_FFS(&domain.ds_mask) - 1;
|
|
|
|
/* This will be constrained by domainset_shadow(). */
|
2019-09-01 21:38:08 +00:00
|
|
|
DOMAINSET_COPY(&all_domains, &domain.ds_mask);
|
2018-01-12 22:48:23 +00:00
|
|
|
}
|
|
|
|
|
2018-10-01 14:14:21 +00:00
|
|
|
/*
|
2019-09-01 21:38:08 +00:00
|
|
|
* When given an impossible policy, fall back to interleaving
|
|
|
|
* across all domains.
|
2018-10-01 14:14:21 +00:00
|
|
|
*/
|
|
|
|
if (domainset_empty_vm(&domain))
|
2021-04-14 16:56:39 +00:00
|
|
|
domainset_copy(domainset2, &domain);
|
2018-10-01 14:14:21 +00:00
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
switch (level) {
|
|
|
|
case CPU_LEVEL_ROOT:
|
|
|
|
case CPU_LEVEL_CPUSET:
|
|
|
|
error = cpuset_which(which, id, &p, &ttd, &set);
|
|
|
|
if (error)
|
|
|
|
break;
|
|
|
|
switch (which) {
|
|
|
|
case CPU_WHICH_TID:
|
|
|
|
case CPU_WHICH_PID:
|
2023-01-30 16:28:54 +00:00
|
|
|
case CPU_WHICH_TIDPID:
|
2018-01-12 22:48:23 +00:00
|
|
|
thread_lock(ttd);
|
|
|
|
set = cpuset_ref(ttd->td_cpuset);
|
|
|
|
thread_unlock(ttd);
|
|
|
|
PROC_UNLOCK(p);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_CPUSET:
|
|
|
|
case CPU_WHICH_JAIL:
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_IRQ:
|
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
|
|
|
case CPU_WHICH_DOMAIN:
|
|
|
|
error = EINVAL;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (level == CPU_LEVEL_ROOT)
|
|
|
|
nset = cpuset_refroot(set);
|
|
|
|
else
|
|
|
|
nset = cpuset_refbase(set);
|
|
|
|
error = cpuset_modify_domain(nset, &domain);
|
|
|
|
cpuset_rel(nset);
|
|
|
|
cpuset_rel(set);
|
|
|
|
break;
|
|
|
|
case CPU_LEVEL_WHICH:
|
|
|
|
switch (which) {
|
|
|
|
case CPU_WHICH_TID:
|
|
|
|
error = _cpuset_setthread(id, NULL, &domain);
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_PID:
|
kern: cpuset: properly rebase when attaching to a jail
The current logic is a fine choice for a system administrator modifying
process cpusets or a process creating a new cpuset(2), but not ideal for
processes attaching to a jail.
Currently, when a process attaches to a jail, it does exactly what any other
process does and loses any mask it might have applied in the process of
doing so because cpuset_setproc() is entirely based around the assumption
that non-anonymous cpusets in the process can be replaced with the new
parent set.
This approach slightly improves the jail attach integration by modifying
cpuset_setproc() callers to indicate if they should rebase their cpuset to
the indicated set or not (i.e. cpuset_setproc_update_set).
If we're rebasing and the process currently has a cpuset assigned that is
not the containing jail's root set, then we will now create a new base set
for it hanging off the jail's root with the existing mask applied instead of
using the jail's root set as the new base set.
Note that the common case will be that the process doesn't have a cpuset
within the jail root, but the system root can freely assign a cpuset from
a jail to a process outside of the jail with no restriction. We assume that
that may have happened or that it could happen due to a race when we drop
the proc lock, so we must recheck both within the loop to gather up
sufficient freed cpusets and after the loop.
To recap, here's how it worked before in all cases:
0 4 <-- jail 0 4 <-- jail / process
| |
1 -> 1
|
3 <-- process
Here's how it works now:
0 4 <-- jail 0 4 <-- jail
| | |
1 -> 1 5 <-- process
|
3 <-- process
or
0 4 <-- jail 0 4 <-- jail / process
| |
1 <-- process -> 1
More importantly, in both cases, the attaching process still retains the
mask it had prior to attaching or the attach fails with EDEADLK if it's
left with no CPUs to run on or the domain policy is incompatible. The
author of this patch considers this almost a security feature, because a MAC
policy could grant PRIV_JAIL_ATTACH to an unprivileged user that's
restricted to some subset of available CPUs the ability to attach to a jail,
which might lift the user's restrictions if they attach to a jail with a
wider mask.
In most cases, it's anticipated that admins will use this to be able to,
for example, `cpuset -c -l 1 jail -c path=/ command=/long/running/cmd`,
and avoid the need for contortions to spawn a command inside a jail with a
more limited cpuset than the jail.
Reviewed by: jamie
MFC after: 1 month (maybe)
Differential Revision: https://reviews.freebsd.org/D27298
2020-11-25 03:14:25 +00:00
|
|
|
error = cpuset_setproc(id, NULL, NULL, &domain, false);
|
2018-01-12 22:48:23 +00:00
|
|
|
break;
|
2023-01-30 16:28:54 +00:00
|
|
|
case CPU_WHICH_TIDPID:
|
|
|
|
if (id > PID_MAX || id == -1)
|
|
|
|
error = _cpuset_setthread(id, NULL, &domain);
|
|
|
|
else
|
|
|
|
error = cpuset_setproc(id, NULL, NULL, &domain,
|
|
|
|
false);
|
|
|
|
break;
|
2018-01-12 22:48:23 +00:00
|
|
|
case CPU_WHICH_CPUSET:
|
|
|
|
case CPU_WHICH_JAIL:
|
|
|
|
error = cpuset_which(which, id, &p, &ttd, &set);
|
|
|
|
if (error == 0) {
|
|
|
|
error = cpuset_modify_domain(set, &domain);
|
|
|
|
cpuset_rel(set);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case CPU_WHICH_IRQ:
|
|
|
|
case CPU_WHICH_INTRHANDLER:
|
|
|
|
case CPU_WHICH_ITHREAD:
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
error = EINVAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
out:
|
|
|
|
free(mask, M_TEMP);
|
|
|
|
return (error);
|
|
|
|
}
|
|
|
|
|
2008-07-07 21:32:02 +00:00
|
|
|
#ifdef DDB
|
2018-03-29 02:54:50 +00:00
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
static void
|
|
|
|
ddb_display_bitset(const struct bitset *set, int size)
|
2013-06-25 18:44:15 +00:00
|
|
|
{
|
2018-01-12 22:48:23 +00:00
|
|
|
int bit, once;
|
2013-06-25 18:44:15 +00:00
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
for (once = 0, bit = 0; bit < size; bit++) {
|
|
|
|
if (CPU_ISSET(bit, set)) {
|
2013-06-25 18:44:15 +00:00
|
|
|
if (once == 0) {
|
2018-01-12 22:48:23 +00:00
|
|
|
db_printf("%d", bit);
|
2013-06-25 18:44:15 +00:00
|
|
|
once = 1;
|
|
|
|
} else
|
2018-01-12 22:48:23 +00:00
|
|
|
db_printf(",%d", bit);
|
2013-06-25 18:44:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (once == 0)
|
|
|
|
db_printf("<none>");
|
|
|
|
}
|
|
|
|
|
2018-01-12 22:48:23 +00:00
|
|
|
void
|
|
|
|
ddb_display_cpuset(const cpuset_t *set)
|
|
|
|
{
|
|
|
|
ddb_display_bitset((const struct bitset *)set, CPU_SETSIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
ddb_display_domainset(const domainset_t *set)
|
|
|
|
{
|
|
|
|
ddb_display_bitset((const struct bitset *)set, DOMAINSET_SETSIZE);
|
|
|
|
}
|
|
|
|
|
2022-07-18 21:21:38 +00:00
|
|
|
DB_SHOW_COMMAND_FLAGS(cpusets, db_show_cpusets, DB_CMD_MEMSAFE)
|
2008-07-07 21:32:02 +00:00
|
|
|
{
|
|
|
|
struct cpuset *set;
|
|
|
|
|
|
|
|
LIST_FOREACH(set, &cpuset_ids, cs_link) {
|
|
|
|
db_printf("set=%p id=%-6u ref=%-6d flags=0x%04x parent id=%d\n",
|
2020-11-17 00:04:05 +00:00
|
|
|
set, set->cs_id, refcount_load(&set->cs_ref), set->cs_flags,
|
2008-07-07 21:32:02 +00:00
|
|
|
(set->cs_parent != NULL) ? set->cs_parent->cs_id : 0);
|
2018-01-12 22:48:23 +00:00
|
|
|
db_printf(" cpu mask=");
|
2013-06-25 18:44:15 +00:00
|
|
|
ddb_display_cpuset(&set->cs_mask);
|
2008-07-07 21:32:02 +00:00
|
|
|
db_printf("\n");
|
2018-01-12 22:48:23 +00:00
|
|
|
db_printf(" domain policy %d prefer %d mask=",
|
|
|
|
set->cs_domain->ds_policy, set->cs_domain->ds_prefer);
|
|
|
|
ddb_display_domainset(&set->cs_domain->ds_mask);
|
|
|
|
db_printf("\n");
|
2008-07-07 21:32:02 +00:00
|
|
|
if (db_pager_quit)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2018-01-12 22:48:23 +00:00
|
|
|
|
2022-07-18 21:21:38 +00:00
|
|
|
DB_SHOW_COMMAND_FLAGS(domainsets, db_show_domainsets, DB_CMD_MEMSAFE)
|
2018-01-12 22:48:23 +00:00
|
|
|
{
|
|
|
|
struct domainset *set;
|
|
|
|
|
|
|
|
LIST_FOREACH(set, &cpuset_domains, ds_link) {
|
2018-03-29 02:54:50 +00:00
|
|
|
db_printf("set=%p policy %d prefer %d cnt %d\n",
|
|
|
|
set, set->ds_policy, set->ds_prefer, set->ds_cnt);
|
2018-01-12 22:48:23 +00:00
|
|
|
db_printf(" mask =");
|
|
|
|
ddb_display_domainset(&set->ds_mask);
|
|
|
|
db_printf("\n");
|
|
|
|
}
|
|
|
|
}
|
2008-07-07 21:32:02 +00:00
|
|
|
#endif /* DDB */
|