libthr: Fix pthread_attr_[g|s]etaffinity_np to match it's manual and the kernel.

Since f35093f8 semantics of a thread affinity functions is changed to be a
compatible with Linux:

In case of getaffinity(), the minimum cpuset_t size that the kernel permits is
the maximum CPU id, present in the system, / NBBY bytes, the maximum size is not
limited.
In case of setaffinity(), the kernel does not limit the size of the user-provided
cpuset_t, internally using only the meaningful part of the set, where the upper
bound is the maximum CPU id, present in the system, no larger than the size of
the kernel cpuset_t.

To match pthread_attr_[g|s]etaffinity_np checks of the user-provided cpusets to
the kernel behavior export the minimum cpuset_t size allowed by running kernel
via new sysctl kern.sched.cpusetsizemin and use it in checks.

Reviewed by:
Differential Revision:	https://reviews.freebsd.org/D38112
MFC after:		1 week
This commit is contained in:
Dmitry Chagin 2023-01-29 15:35:18 +03:00
parent 02f7670ed2
commit 01f74ccd5a
4 changed files with 13 additions and 2 deletions

View File

@ -599,8 +599,10 @@ _get_kern_cpuset_size(void)
size_t len;
len = sizeof(kern_cpuset_size);
if (sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size,
&len, NULL, 0))
if (sysctlbyname("kern.sched.cpusetsizemin", &kern_cpuset_size,
&len, NULL, 0) != 0 &&
sysctlbyname("kern.sched.cpusetsize", &kern_cpuset_size,
&len, NULL, 0) != 0)
PANIC("failed to get sysctl kern.sched.cpusetsize");
}

View File

@ -136,11 +136,17 @@ static struct domainlist cpuset_domains;
static struct unrhdr *cpuset_unr;
static struct cpuset *cpuset_zero, *cpuset_default, *cpuset_kernel;
static struct domainset *domainset0, *domainset2;
u_int cpusetsizemin = 1;
/* Return the size of cpuset_t at the kernel level */
SYSCTL_INT(_kern_sched, OID_AUTO, cpusetsize, CTLFLAG_RD | CTLFLAG_CAPRD,
SYSCTL_NULL_INT_PTR, sizeof(cpuset_t), "sizeof(cpuset_t)");
/* 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");
cpuset_t *cpuset_root;
cpuset_t cpuset_domain[MAXMEMDOM];

View File

@ -148,6 +148,8 @@ mp_setmaxid(void *dummy)
KASSERT(mp_maxid >= mp_ncpus - 1,
("%s: counters out of sync: max %d, count %d", __func__,
mp_maxid, mp_ncpus));
cpusetsizemin = howmany(mp_maxid + 1, NBBY);
}
SYSINIT(cpu_mp_setmaxid, SI_SUB_TUNABLES, SI_ORDER_FIRST, mp_setmaxid, NULL);

View File

@ -120,6 +120,7 @@
#include <sys/queue.h>
LIST_HEAD(setlist, cpuset);
extern u_int cpusetsizemin;
/*
* cpusets encapsulate cpu binding information for one or more threads.