diff options
Diffstat (limited to 'libs/pthreads/src/pthread_setaffinity.c')
-rw-r--r-- | libs/pthreads/src/pthread_setaffinity.c | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/libs/pthreads/src/pthread_setaffinity.c b/libs/pthreads/src/pthread_setaffinity.c new file mode 100644 index 0000000000..81baaf8784 --- /dev/null +++ b/libs/pthreads/src/pthread_setaffinity.c @@ -0,0 +1,242 @@ +/* + * pthread_setaffinity.c + * + * Description: + * This translation unit implements thread cpu affinity setting. + * + * -------------------------------------------------------------------------- + * + * 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" + +int +pthread_setaffinity_np (pthread_t thread, size_t cpusetsize, + const cpu_set_t *cpuset) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * The pthread_setaffinity_np() function sets the CPU affinity mask + * of the thread thread to the CPU set pointed to by cpuset. If the + * call is successful, and the thread is not currently running on one + * of the CPUs in cpuset, then it is migrated to one of those CPUs. + * + * PARAMETERS + * thread + * The target thread + * + * cpusetsize + * Ignored in pthreads4w. + * Usually set to sizeof(cpu_set_t) + * + * cpuset + * The new cpu set mask. + * + * The set of CPUs on which the thread will actually run + * is the intersection of the set specified in the cpuset + * argument and the set of CPUs actually present for + * the process. + * + * DESCRIPTION + * The pthread_setaffinity_np() function sets the CPU affinity mask + * of the thread thread to the CPU set pointed to by cpuset. If the + * call is successful, and the thread is not currently running on one + * of the CPUs in cpuset, then it is migrated to one of those CPUs. + * + * RESULTS + * 0 Success + * ESRCH Thread does not exist + * EFAULT pcuset is NULL + * EAGAIN The thread affinity could not be set + * ENOSYS The platform does not support this function + * + * ------------------------------------------------------ + */ +{ +#if ! defined(HAVE_CPU_AFFINITY) + + return ENOSYS; + +#else + + int result = 0; + ptw32_thread_t * tp; + ptw32_mcs_local_node_t node; + cpu_set_t processCpuset; + + ptw32_mcs_lock_acquire (&ptw32_thread_reuse_lock, &node); + + tp = (ptw32_thread_t *) thread.p; + + if (NULL == tp || thread.x != tp->ptHandle.x || NULL == tp->threadH) + { + result = ESRCH; + } + else + { + if (cpuset) + { + if (sched_getaffinity(0, sizeof(cpu_set_t), &processCpuset)) + { + result = PTW32_GET_ERRNO(); + } + else + { + /* + * Result is the intersection of available CPUs and the mask. + */ + cpu_set_t newMask; + + CPU_AND(&newMask, &processCpuset, cpuset); + + if (((_sched_cpu_set_vector_*)&newMask)->_cpuset) + { + if (SetThreadAffinityMask (tp->threadH, ((_sched_cpu_set_vector_*)&newMask)->_cpuset)) + { + /* + * We record the intersection of the process affinity + * and the thread affinity cpusets so that + * pthread_getaffinity_np() returns the actual thread + * CPU set. + */ + tp->cpuset = ((_sched_cpu_set_vector_*)&newMask)->_cpuset; + } + else + { + result = EAGAIN; + } + } + else + { + result = EINVAL; + } + } + } + else + { + result = EFAULT; + } + } + + ptw32_mcs_lock_release (&node); + + return result; + +#endif +} + +int +pthread_getaffinity_np (pthread_t thread, size_t cpusetsize, cpu_set_t *cpuset) + /* + * ------------------------------------------------------ + * DOCPUBLIC + * The pthread_getaffinity_np() function returns the CPU affinity mask + * of the thread thread in the CPU set pointed to by cpuset. + * + * PARAMETERS + * thread + * The target thread + * + * cpusetsize + * Ignored in pthreads4w. + * Usually set to sizeof(cpu_set_t) + * + * cpuset + * The location where the current cpu set + * will be returned. + * + * + * DESCRIPTION + * The pthread_getaffinity_np() function returns the CPU affinity mask + * of the thread thread in the CPU set pointed to by cpuset. + * + * RESULTS + * 0 Success + * ESRCH thread does not exist + * EFAULT cpuset is NULL + * ENOSYS The platform does not support this function + * + * ------------------------------------------------------ + */ +{ +#if ! defined(HAVE_CPU_AFFINITY) + + return ENOSYS; + +#else + + int result = 0; + ptw32_thread_t * tp; + ptw32_mcs_local_node_t node; + + ptw32_mcs_lock_acquire(&ptw32_thread_reuse_lock, &node); + + tp = (ptw32_thread_t *) thread.p; + + if (NULL == tp || thread.x != tp->ptHandle.x || NULL == tp->threadH) + { + result = ESRCH; + } + else + { + if (cpuset) + { + if (tp->cpuset) + { + /* + * The application may have set thread affinity independently + * via SetThreadAffinityMask(). If so, we adjust our record of the threads + * affinity and try to do so in a reasonable way. + */ + DWORD_PTR vThreadMask = SetThreadAffinityMask(tp->threadH, tp->cpuset); + if (vThreadMask && vThreadMask != tp->cpuset) + { + (void) SetThreadAffinityMask(tp->threadH, vThreadMask); + tp->cpuset = vThreadMask; + } + } + ((_sched_cpu_set_vector_*)cpuset)->_cpuset = tp->cpuset; + } + else + { + result = EFAULT; + } + } + + ptw32_mcs_lock_release(&node); + + return result; + +#endif +} |