From 98734cc50153c80047f4ed9c6772bc7e1e68c9f7 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Mon, 23 Mar 2015 16:34:48 +0100 Subject: [PATCH] pthread_setaffinity (Linux variant): Rewrite to use VLA instead of alloca extend_alloca was used to emulate VLA deallocation. The new version also handles the res == 0 corner case more explicitly, by returning 0 instead of the (potentially undefined, but usually zero) system call error. --- ChangeLog | 6 ++++ sysdeps/unix/sysv/linux/pthread_setaffinity.c | 31 ++++++++++--------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/ChangeLog b/ChangeLog index c1b91061ba..5686701994 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2015-03-23 Florian Weimer + + * sysdeps/unix/sysv/linux/pthread_setaffinity.c + (__determine_cpumask_size): Replace extend_alloca with a + variable-length array. Do not treat res == 0 as an error. + 2015-03-23 Florian Weimer [BZ #18100] diff --git a/sysdeps/unix/sysv/linux/pthread_setaffinity.c b/sysdeps/unix/sysv/linux/pthread_setaffinity.c index 37997e9688..e891818e8b 100644 --- a/sysdeps/unix/sysv/linux/pthread_setaffinity.c +++ b/sysdeps/unix/sysv/linux/pthread_setaffinity.c @@ -16,7 +16,6 @@ License along with the GNU C Library; if not, see . */ -#include #include #include #include @@ -27,26 +26,30 @@ size_t __kernel_cpumask_size attribute_hidden; -/* Determine the current affinity. As a side affect we learn - about the size of the cpumask_t in the kernel. */ +/* Determine the size of cpumask_t in the kernel. */ int __determine_cpumask_size (pid_t tid) { - INTERNAL_SYSCALL_DECL (err); + size_t psize; int res; - size_t psize = 128; - void *p = alloca (psize); + for (psize = 128; ; psize *= 2) + { + char buf[psize]; + INTERNAL_SYSCALL_DECL (err); - while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, tid, psize, p), - INTERNAL_SYSCALL_ERROR_P (res, err) - && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL) - p = extend_alloca (p, psize, 2 * psize); + res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, tid, psize, buf); + if (INTERNAL_SYSCALL_ERROR_P (res, err)) + { + if (INTERNAL_SYSCALL_ERRNO (res, err) != EINVAL) + return INTERNAL_SYSCALL_ERRNO (res, err); + } + else + break; + } - if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err)) - return INTERNAL_SYSCALL_ERRNO (res, err); - - __kernel_cpumask_size = res; + if (res != 0) + __kernel_cpumask_size = res; return 0; }