aboutsummaryrefslogtreecommitdiff
path: root/pthreads/sched_setaffinity.c
diff options
context:
space:
mode:
Diffstat (limited to 'pthreads/sched_setaffinity.c')
-rwxr-xr-xpthreads/sched_setaffinity.c352
1 files changed, 352 insertions, 0 deletions
diff --git a/pthreads/sched_setaffinity.c b/pthreads/sched_setaffinity.c
new file mode 100755
index 000000000..07b0fb4f4
--- /dev/null
+++ b/pthreads/sched_setaffinity.c
@@ -0,0 +1,352 @@
+/*
+ * sched_setaffinity.c
+ *
+ * Description:
+ * POSIX scheduling functions that deal with CPU affinity.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2012 Pthreads-win32 contributors
+ *
+ * Homepage1: http://sourceware.org/pthreads-win32/
+ * Homepage2: http://sourceforge.net/projects/pthreads4w/
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "pthread.h"
+#include "implement.h"
+#include "sched.h"
+
+int
+sched_setaffinity (pid_t pid, size_t cpusetsize, cpu_set_t *set)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Sets the CPU affinity mask of the process whose ID is pid
+ * to the value specified by mask. If pid is zero, then the
+ * calling process is used. The argument cpusetsize is the
+ * length (in bytes) of the data pointed to by mask. Normally
+ * this argument would be specified as sizeof(cpu_set_t).
+ *
+ * If the process specified by pid is not currently running on
+ * one of the CPUs specified in mask, then that process is
+ * migrated to one of the CPUs specified in mask.
+ *
+ * PARAMETERS
+ * pid
+ * Process ID
+ *
+ * cpusetsize
+ * Currently ignored in pthreads4w.
+ * Usually set to sizeof(cpu_set_t)
+ *
+ * mask
+ * Pointer to the CPU mask to set (cpu_set_t).
+ *
+ * DESCRIPTION
+ * Sets the CPU affinity mask of the process whose ID is pid
+ * to the value specified by mask. If pid is zero, then the
+ * calling process is used. The argument cpusetsize is the
+ * length (in bytes) of the data pointed to by mask. Normally
+ * this argument would be specified as sizeof(cpu_set_t).
+ *
+ * If the process specified by pid is not currently running on
+ * one of the CPUs specified in mask, then that process is
+ * migrated to one of the CPUs specified in mask.
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * EFAULT 'mask' is a NULL pointer.
+ * EINVAL '*mask' contains no CPUs in the set
+ * of available CPUs.
+ * EAGAIN The system available CPUs could not
+ * be obtained.
+ * EPERM The process referred to by 'pid' is
+ * not modifiable by us.
+ * ESRCH The process referred to by 'pid' was
+ * not found.
+ * ENOSYS Function not supported.
+ *
+ * ------------------------------------------------------
+ */
+{
+#if ! defined(NEED_PROCESS_AFFINITY_MASK)
+
+ DWORD_PTR vProcessMask;
+ DWORD_PTR vSystemMask;
+ HANDLE h;
+ int targetPid = (int)(size_t) pid;
+ int result = 0;
+
+ if (NULL == set)
+ {
+ result = EFAULT;
+ }
+ else
+ {
+ if (0 == targetPid)
+ {
+ targetPid = (int) GetCurrentProcessId ();
+ }
+
+ h = OpenProcess (PROCESS_QUERY_INFORMATION|PROCESS_SET_INFORMATION, PTW32_FALSE, (DWORD) targetPid);
+
+ if (NULL == h)
+ {
+ result = (((0xFF & ERROR_ACCESS_DENIED) == GetLastError()) ? EPERM : ESRCH);
+ }
+ else
+ {
+ if (GetProcessAffinityMask (h, &vProcessMask, &vSystemMask))
+ {
+ /*
+ * Result is the intersection of available CPUs and the mask.
+ */
+ DWORD_PTR newMask = vSystemMask & ((_sched_cpu_set_vector_*)set)->_cpuset;
+
+ if (newMask)
+ {
+ if (SetProcessAffinityMask(h, newMask) == 0)
+ {
+ switch (GetLastError())
+ {
+ case (0xFF & ERROR_ACCESS_DENIED):
+ result = EPERM;
+ break;
+ case (0xFF & ERROR_INVALID_PARAMETER):
+ result = EINVAL;
+ break;
+ default:
+ result = EAGAIN;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Mask does not contain any CPUs currently available on the system.
+ */
+ result = EINVAL;
+ }
+ }
+ else
+ {
+ result = EAGAIN;
+ }
+ }
+ CloseHandle(h);
+ }
+
+ if (result != 0)
+ {
+ PTW32_SET_ERRNO(result);
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+
+#else
+
+ PTW32_SET_ERRNO(ENOSYS);
+ return -1;
+
+#endif
+}
+
+
+int
+sched_getaffinity (pid_t pid, size_t cpusetsize, cpu_set_t *set)
+ /*
+ * ------------------------------------------------------
+ * DOCPUBLIC
+ * Gets the CPU affinity mask of the process whose ID is pid
+ * to the value specified by mask. If pid is zero, then the
+ * calling process is used. The argument cpusetsize is the
+ * length (in bytes) of the data pointed to by mask. Normally
+ * this argument would be specified as sizeof(cpu_set_t).
+ *
+ * PARAMETERS
+ * pid
+ * Process ID
+ *
+ * cpusetsize
+ * Currently ignored in pthreads4w.
+ * Usually set to sizeof(cpu_set_t)
+ *
+ * mask
+ * Pointer to the CPU mask to set (cpu_set_t).
+ *
+ * DESCRIPTION
+ * Sets the CPU affinity mask of the process whose ID is pid
+ * to the value specified by mask. If pid is zero, then the
+ * calling process is used. The argument cpusetsize is the
+ * length (in bytes) of the data pointed to by mask. Normally
+ * this argument would be specified as sizeof(cpu_set_t).
+ *
+ * RESULTS
+ * 0 successfully created semaphore,
+ * EFAULT 'mask' is a NULL pointer.
+ * EAGAIN The system available CPUs could not
+ * be obtained.
+ * EPERM The process referred to by 'pid' is
+ * not modifiable by us.
+ * ESRCH The process referred to by 'pid' was
+ * not found.
+ *
+ * ------------------------------------------------------
+ */
+{
+ DWORD_PTR vProcessMask;
+ DWORD_PTR vSystemMask;
+ HANDLE h;
+ int targetPid = (int)(size_t) pid;
+ int result = 0;
+
+ if (NULL == set)
+ {
+ result = EFAULT;
+ }
+ else
+ {
+
+#if ! defined(NEED_PROCESS_AFFINITY_MASK)
+
+ if (0 == targetPid)
+ {
+ targetPid = (int) GetCurrentProcessId ();
+ }
+
+ h = OpenProcess (PROCESS_QUERY_INFORMATION, PTW32_FALSE, (DWORD) targetPid);
+
+ if (NULL == h)
+ {
+ result = (((0xFF & ERROR_ACCESS_DENIED) == GetLastError()) ? EPERM : ESRCH);
+ }
+ else
+ {
+ if (GetProcessAffinityMask (h, &vProcessMask, &vSystemMask))
+ {
+ ((_sched_cpu_set_vector_*)set)->_cpuset = vProcessMask;
+ }
+ else
+ {
+ result = EAGAIN;
+ }
+ }
+ CloseHandle(h);
+
+#else
+ ((_sched_cpu_set_vector_*)set)->_cpuset = (size_t)0x1;
+#endif
+
+ }
+
+ if (result != 0)
+ {
+ PTW32_SET_ERRNO(result);
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/*
+ * Support routines for cpu_set_t
+ */
+int _sched_affinitycpucount (const cpu_set_t *set)
+{
+ size_t tset;
+ int count;
+
+ /*
+ * Relies on tset being unsigned, otherwise the right-shift will
+ * be arithmetic rather than logical and the 'for' will loop forever.
+ */
+ for (count = 0, tset = ((_sched_cpu_set_vector_*)set)->_cpuset; tset; tset >>= 1)
+ {
+ if (tset & (size_t)1)
+ {
+ count++;
+ }
+ }
+ return count;
+}
+
+void _sched_affinitycpuzero (cpu_set_t *pset)
+{
+ ((_sched_cpu_set_vector_*)pset)->_cpuset = (size_t)0;
+}
+
+void _sched_affinitycpuset (int cpu, cpu_set_t *pset)
+{
+ ((_sched_cpu_set_vector_*)pset)->_cpuset |= ((size_t)1 << cpu);
+}
+
+void _sched_affinitycpuclr (int cpu, cpu_set_t *pset)
+{
+ ((_sched_cpu_set_vector_*)pset)->_cpuset &= ~((size_t)1 << cpu);
+}
+
+int _sched_affinitycpuisset (int cpu, const cpu_set_t *pset)
+{
+ return ((((_sched_cpu_set_vector_*)pset)->_cpuset &
+ ((size_t)1 << cpu)) != (size_t)0);
+}
+
+void _sched_affinitycpuand(cpu_set_t *pdestset, const cpu_set_t *psrcset1, const cpu_set_t *psrcset2)
+{
+ ((_sched_cpu_set_vector_*)pdestset)->_cpuset =
+ (((_sched_cpu_set_vector_*)psrcset1)->_cpuset &
+ ((_sched_cpu_set_vector_*)psrcset2)->_cpuset);
+}
+
+void _sched_affinitycpuor(cpu_set_t *pdestset, const cpu_set_t *psrcset1, const cpu_set_t *psrcset2)
+{
+ ((_sched_cpu_set_vector_*)pdestset)->_cpuset =
+ (((_sched_cpu_set_vector_*)psrcset1)->_cpuset |
+ ((_sched_cpu_set_vector_*)psrcset2)->_cpuset);
+}
+
+void _sched_affinitycpuxor(cpu_set_t *pdestset, const cpu_set_t *psrcset1, const cpu_set_t *psrcset2)
+{
+ ((_sched_cpu_set_vector_*)pdestset)->_cpuset =
+ (((_sched_cpu_set_vector_*)psrcset1)->_cpuset ^
+ ((_sched_cpu_set_vector_*)psrcset2)->_cpuset);
+}
+
+int _sched_affinitycpuequal (const cpu_set_t *pset1, const cpu_set_t *pset2)
+{
+ return (((_sched_cpu_set_vector_*)pset1)->_cpuset ==
+ ((_sched_cpu_set_vector_*)pset2)->_cpuset);
+}