/* * 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 #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); }