Back to index

glibc  2.9
sched_setaffinity.c
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004, 2005, 2007
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <errno.h>
00021 #include <sched.h>
00022 #include <string.h>
00023 #include <sysdep.h>
00024 #include <unistd.h>
00025 #include <sys/types.h>
00026 #include <shlib-compat.h>
00027 #include <alloca.h>
00028 
00029 
00030 #ifdef __NR_sched_setaffinity
00031 static size_t __kernel_cpumask_size;
00032 
00033 
00034 int
00035 __sched_setaffinity_new (pid_t pid, size_t cpusetsize, const cpu_set_t *cpuset)
00036 {
00037   if (__builtin_expect (__kernel_cpumask_size == 0, 0))
00038     {
00039       INTERNAL_SYSCALL_DECL (err);
00040       int res;
00041 
00042       size_t psize = 128;
00043       void *p = alloca (psize);
00044 
00045       while (res = INTERNAL_SYSCALL (sched_getaffinity, err, 3, getpid (),
00046                                  psize, p),
00047             INTERNAL_SYSCALL_ERROR_P (res, err)
00048             && INTERNAL_SYSCALL_ERRNO (res, err) == EINVAL)
00049        p = extend_alloca (p, psize, 2 * psize);
00050 
00051       if (res == 0 || INTERNAL_SYSCALL_ERROR_P (res, err))
00052        {
00053          __set_errno (INTERNAL_SYSCALL_ERRNO (res, err));
00054          return -1;
00055        }
00056 
00057       __kernel_cpumask_size = res;
00058     }
00059 
00060   /* We now know the size of the kernel cpumask_t.  Make sure the user
00061      does not request to set a bit beyond that.  */
00062   for (size_t cnt = __kernel_cpumask_size; cnt < cpusetsize; ++cnt)
00063     if (((char *) cpuset)[cnt] != '\0')
00064       {
00065         /* Found a nonzero byte.  This means the user request cannot be
00066           fulfilled.  */
00067        __set_errno (EINVAL);
00068        return -1;
00069       }
00070 
00071   int result = INLINE_SYSCALL (sched_setaffinity, 3, pid, cpusetsize, cpuset);
00072 
00073 #ifdef RESET_VGETCPU_CACHE
00074   if (result != -1)
00075     RESET_VGETCPU_CACHE ();
00076 #endif
00077 
00078   return result;
00079 }
00080 versioned_symbol (libc, __sched_setaffinity_new, sched_setaffinity,
00081                 GLIBC_2_3_4);
00082 
00083 
00084 # if SHLIB_COMPAT (libc, GLIBC_2_3_3, GLIBC_2_3_4)
00085 int
00086 attribute_compat_text_section
00087 __sched_setaffinity_old (pid_t pid, const cpu_set_t *cpuset)
00088 {
00089   /* The old interface by default assumed a 1024 processor bitmap.  */
00090   return __sched_setaffinity_new (pid, 128, cpuset);
00091 }
00092 compat_symbol (libc, __sched_setaffinity_old, sched_setaffinity, GLIBC_2_3_3);
00093 # endif
00094 #else
00095 # include <posix/sched_setaffinity.c>
00096 #endif