summaryrefslogtreecommitdiffstats
path: root/lib/libthr
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2008-03-05 06:55:48 +0000
committerdavidxu <davidxu@FreeBSD.org>2008-03-05 06:55:48 +0000
commitadf8d28a8fa1f5e5bcaf3db35eba931eaa2bab9f (patch)
tree215f8f14211f48d974618fa5aec10a62a69f28ab /lib/libthr
parent44702a8a45bbd9c71ef5e5d962789895f76c4af3 (diff)
downloadFreeBSD-src-adf8d28a8fa1f5e5bcaf3db35eba931eaa2bab9f.zip
FreeBSD-src-adf8d28a8fa1f5e5bcaf3db35eba931eaa2bab9f.tar.gz
Check actual size of cpuset kernel is using and define underscore version
of API.
Diffstat (limited to 'lib/libthr')
-rw-r--r--lib/libthr/thread/thr_attr.c49
1 files changed, 42 insertions, 7 deletions
diff --git a/lib/libthr/thread/thr_attr.c b/lib/libthr/thread/thr_attr.c
index 3e5b4bf..cd13553 100644
--- a/lib/libthr/thread/thr_attr.c
+++ b/lib/libthr/thread/thr_attr.c
@@ -99,6 +99,7 @@
#include <stdlib.h>
#include <string.h>
#include <pthread_np.h>
+#include <sys/sysctl.h>
#include "un-namespace.h"
#include "thr_private.h"
@@ -546,8 +547,28 @@ _pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize)
return(ret);
}
+static int
+_get_kern_cpuset_size()
+{
+ static int kern_cpuset_size = 0;
+
+ if (kern_cpuset_size == 0) {
+ int len;
+
+ len = sizeof(kern_cpuset_size);
+ if (sysctlbyname("kern.smp.maxcpus", &kern_cpuset_size,
+ &len, NULL, 0))
+ PANIC("failed to get sysctl kern.smp.maxcpus");
+
+ kern_cpuset_size = (kern_cpuset_size + 7) / 8;
+ }
+
+ return (kern_cpuset_size);
+}
+
+__weak_reference(_pthread_attr_setaffinity_np, pthread_attr_setaffinity_np);
int
-pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
+_pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
const cpuset_t *cpuset)
{
pthread_attr_t attr;
@@ -565,15 +586,24 @@ pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
return (0);
}
- /*
- * XXX figure out kernel cpuset size, reject invalid size.
- */
- if (cpusetsize != attr->cpusetsize) {
+ if (cpusetsize > attr->cpusetsize) {
+ int kern_size = _get_kern_cpuset_size();
+ if (cpusetsize > kern_size) {
+ int i;
+ for (i = kern_size; i < cpusetsize; ++i) {
+ if (((char *)cpuset)[i])
+ return (EINVAL);
+ }
+ }
void *newset = realloc(attr->cpuset, cpusetsize);
if (newset == NULL)
return (ENOMEM);
attr->cpuset = newset;
attr->cpusetsize = cpusetsize;
+ } else {
+ memset(((char *)attr->cpuset) + cpusetsize, 0,
+ cpusetsize - attr->cpusetsize);
+ attr->cpusetsize = cpusetsize;
}
memcpy(attr->cpuset, cpuset, cpusetsize);
ret = 0;
@@ -581,8 +611,9 @@ pthread_attr_setaffinity_np(pthread_attr_t *pattr, size_t cpusetsize,
return (ret);
}
+__weak_reference(_pthread_attr_getaffinity_np, pthread_attr_getaffinity_np);
int
-pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize,
+_pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize,
cpuset_t *cpuset)
{
pthread_attr_t attr;
@@ -596,7 +627,11 @@ pthread_attr_getaffinity_np(const pthread_attr_t *pattr, size_t cpusetsize,
memset(((char *)cpuset) + attr->cpusetsize, 0,
cpusetsize - attr->cpusetsize);
} else {
- memset(cpuset, -1, cpusetsize);
+ int kern_size = _get_kern_cpuset_size();
+ memset(cpuset, -1, MIN(cpusetsize, kern_size));
+ if (cpusetsize > kern_size)
+ memset(((char *)cpuset) + kern_size, 0,
+ cpusetsize - kern_size);
}
return (ret);
}
OpenPOWER on IntegriCloud