summaryrefslogtreecommitdiff
path: root/libs/pthreads/src/sched_setaffinity.c
diff options
context:
space:
mode:
authorGeorge Hazan <ghazan@miranda.im>2021-06-06 22:01:10 +0300
committerGeorge Hazan <ghazan@miranda.im>2021-06-06 22:01:10 +0300
commitb18dd79bc6b6ee3658ef4513665cb84c24030368 (patch)
tree52dcfedbf246865021e0cb0e13f9ff22b08d9504 /libs/pthreads/src/sched_setaffinity.c
parentfedcdca7ed8f402550227c5c6e9c1d28417b896c (diff)
fixes #2909 (pthreads updated to 2.11.0)
Diffstat (limited to 'libs/pthreads/src/sched_setaffinity.c')
-rw-r--r--libs/pthreads/src/sched_setaffinity.c351
1 files changed, 351 insertions, 0 deletions
diff --git a/libs/pthreads/src/sched_setaffinity.c b/libs/pthreads/src/sched_setaffinity.c
new file mode 100644
index 0000000000..de44fd4461
--- /dev/null
+++ b/libs/pthreads/src/sched_setaffinity.c
@@ -0,0 +1,351 @@
+/*
+ * sched_setaffinity.c
+ *
+ * Description:
+ * POSIX scheduling functions that deal with CPU affinity.
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads4w - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999-2018, Pthreads4w contributors
+ *
+ * Homepage: https://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:
+ * https://sourceforge.net/p/pthreads4w/wiki/Contributors/
+ *
+ * This file is part of Pthreads4w.
+ *
+ * Pthreads4w is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Pthreads4w 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Pthreads4w. If not, see <http://www.gnu.org/licenses/>. *
+ */
+
+#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);
+}