pthread_setaffinity (Linux variant): Rewrite to use VLA instead of alloca
authorFlorian Weimer <fweimer@redhat.com>
Mon, 23 Mar 2015 15:34:48 +0000 (16:34 +0100)
committerFlorian Weimer <fweimer@redhat.com>
Mon, 23 Mar 2015 15:34:48 +0000 (16:34 +0100)
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
sysdeps/unix/sysv/linux/pthread_setaffinity.c

index c1b9106..5686701 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2015-03-23  Florian Weimer  <fweimer@redhat.com>
 
+       * 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  <fweimer@redhat.com>
+
        [BZ #18100]
        * posix/wordexp.c (eval_expr_multdiv): Check for division by zero
        and integer overflow.
index 37997e9..e891818 100644 (file)
@@ -16,7 +16,6 @@
    License along with the GNU C Library; if not, see
    <http://www.gnu.org/licenses/>.  */
 
-#include <alloca.h>
 #include <errno.h>
 #include <pthreadP.h>
 #include <sysdep.h>
 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);
-
-  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);
-
-  if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err))
-    return INTERNAL_SYSCALL_ERRNO (res, err);
+  for (psize = 128; ; psize *= 2)
+    {
+      char buf[psize];
+      INTERNAL_SYSCALL_DECL (err);
+
+      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;
+    }
 
-  __kernel_cpumask_size = res;
+  if (res != 0)
+    __kernel_cpumask_size = res;
 
   return 0;
 }