From 1e0a1f59d9e64430ce796c578e0813100c0cf0d7 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 7 Aug 2018 14:51:10 +0200 Subject: [PATCH] Cygwin: implement sched_getcpu * create new function __get_cpus_per_group to evaluate # of CPU groups * Call from format_proc_cpuinfo and sched_getcpu * Bump API minor version Signed-off-by: Corinna Vinschen --- winsup/cygwin/autoload.cc | 1 + winsup/cygwin/common.din | 1 + winsup/cygwin/fhandler_proc.cc | 42 +------------------- winsup/cygwin/include/cygwin/version.h | 3 +- winsup/cygwin/miscfuncs.cc | 53 ++++++++++++++++++++++++++ winsup/cygwin/miscfuncs.h | 2 + winsup/cygwin/release/2.11.0 | 3 +- winsup/cygwin/sched.cc | 13 +++++++ winsup/doc/new-features.xml | 2 +- winsup/doc/posix.xml | 1 + 10 files changed, 77 insertions(+), 44 deletions(-) diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 199821d95..f71abe802 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -580,6 +580,7 @@ LoadDLLfunc (if_indextoname, 8, iphlpapi) LoadDLLfunc (if_nametoindex, 4, iphlpapi) LoadDLLfuncEx2 (DiscardVirtualMemory, 8, kernel32, 1, 127) +LoadDLLfunc (GetCurrentProcessorNumberEx, 4, kernel32) LoadDLLfuncEx (GetLogicalProcessorInformationEx, 12, kernel32, 1) LoadDLLfunc (GetSystemTimePreciseAsFileTime, 4, kernel32) LoadDLLfuncEx (PrefetchVirtualMemory, 16, kernel32, 1) diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din index 312b04c5b..d1d955542 100644 --- a/winsup/cygwin/common.din +++ b/winsup/cygwin/common.din @@ -1249,6 +1249,7 @@ scandirat SIGFE scanf SIGFE sched_get_priority_max SIGFE sched_get_priority_min SIGFE +sched_getcpu SIGFE sched_getparam SIGFE sched_getscheduler NOSIGFE sched_rr_get_interval SIGFE diff --git a/winsup/cygwin/fhandler_proc.cc b/winsup/cygwin/fhandler_proc.cc index 3e25bdc80..c9761b5b9 100644 --- a/winsup/cygwin/fhandler_proc.cc +++ b/winsup/cygwin/fhandler_proc.cc @@ -600,7 +600,6 @@ format_proc_stat (void *, char *&destbuf) return eobuf - buf; } -#define add_size(p,s) ((p) = ((__typeof__(p))((PBYTE)(p)+(s)))) #define print(x) { bufptr = stpcpy (bufptr, (x)); } static inline uint32_t @@ -640,46 +639,7 @@ format_proc_cpuinfo (void *, char *&destbuf) char *bufptr = buf; //WORD num_cpu_groups = 1; /* Pre Windows 7, only one group... */ - WORD num_cpu_per_group = 64; /* ...and a max of 64 CPUs. */ - - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX lpi = - (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) tp.c_get (); - DWORD lpi_size = NT_MAX_PATH; - - /* Fake a SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX group info block on Vista - systems. This may be over the top but if the below code just using - ActiveProcessorCount turns out to be insufficient, we can build on that. */ - if (!wincap.has_processor_groups () - || !GetLogicalProcessorInformationEx (RelationGroup, lpi, &lpi_size)) - { - lpi_size = sizeof *lpi; - lpi->Relationship = RelationGroup; - lpi->Size = lpi_size; - lpi->Group.MaximumGroupCount = 1; - lpi->Group.ActiveGroupCount = 1; - lpi->Group.GroupInfo[0].MaximumProcessorCount = wincap.cpu_count (); - lpi->Group.GroupInfo[0].ActiveProcessorCount - = __builtin_popcountl (wincap.cpu_mask ()); - lpi->Group.GroupInfo[0].ActiveProcessorMask = wincap.cpu_mask (); - } - - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX plpi = lpi; - for (DWORD size = lpi_size; size > 0; - size -= plpi->Size, add_size (plpi, plpi->Size)) - if (plpi->Relationship == RelationGroup) - { - //num_cpu_groups = plpi->Group.MaximumGroupCount; - /* Turns out, there are systems with a MaximumProcessorCount not - reflecting the actually available CPUs. The ActiveProcessorCount - is correct though. So we just use ActiveProcessorCount for now, - hoping the best. If it turns out that we have to handle more - complex CPU layouts with weird ActiveProcessorMasks, we can - do that by restructuring the subsequent CPU loop. */ - num_cpu_per_group - = plpi->Group.GroupInfo[0].ActiveProcessorCount; - break; - } - + WORD num_cpu_per_group = __get_cpus_per_group (); cpu_num_p = wcpcpy (cpu_key, L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION" "\\System\\CentralProcessor\\"); diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 5140dd19d..4f90b8fe5 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -498,12 +498,13 @@ details. */ 327: Export pthread_tryjoin_np, pthread_timedjoin_np. 328: Export aio_cancel, aio_error, aio_fsync, aio_read, aio_return, aio_suspend, aio_write, lio_listio. + 329: Export sched_getcpu.. Note that we forgot to bump the api for ualarm, strtoll, strtoull, sigaltstack, sethostname. */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 328 +#define CYGWIN_VERSION_API_MINOR 329 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible changes are made to the shared diff --git a/winsup/cygwin/miscfuncs.cc b/winsup/cygwin/miscfuncs.cc index 3ad658739..b5dfffc7d 100644 --- a/winsup/cygwin/miscfuncs.cc +++ b/winsup/cygwin/miscfuncs.cc @@ -15,6 +15,7 @@ details. */ #include "path.h" #include "fhandler.h" #include "exception.h" +#include "tls_pbuf.h" int __reg2 check_invalid_virtual_addr (const void *s, unsigned sz) @@ -959,3 +960,55 @@ SetThreadName(DWORD dwThreadID, const char* threadName) __except (NO_ERROR) __endtry } + +#define add_size(p,s) ((p) = ((__typeof__(p))((PBYTE)(p)+(s)))) + +WORD +__get_cpus_per_group (void) +{ + static WORD num_cpu_per_group = 0; + + tmp_pathbuf tp; + + if (num_cpu_per_group) + return num_cpu_per_group; + + num_cpu_per_group = 64; + + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX lpi = + (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX) tp.c_get (); + DWORD lpi_size = NT_MAX_PATH; + + /* Fake a SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX group info block on Vista + systems. This may be over the top but if the below code just using + ActiveProcessorCount turns out to be insufficient, we can build on that. */ + if (!wincap.has_processor_groups () + || !GetLogicalProcessorInformationEx (RelationGroup, lpi, &lpi_size)) + { + lpi_size = sizeof *lpi; + lpi->Relationship = RelationGroup; + lpi->Size = lpi_size; + lpi->Group.MaximumGroupCount = 1; + lpi->Group.ActiveGroupCount = 1; + lpi->Group.GroupInfo[0].MaximumProcessorCount = wincap.cpu_count (); + lpi->Group.GroupInfo[0].ActiveProcessorCount + = __builtin_popcountl (wincap.cpu_mask ()); + lpi->Group.GroupInfo[0].ActiveProcessorMask = wincap.cpu_mask (); + } + + PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX plpi = lpi; + for (DWORD size = lpi_size; size > 0; + size -= plpi->Size, add_size (plpi, plpi->Size)) + if (plpi->Relationship == RelationGroup) + { + /* There are systems with a MaximumProcessorCount not reflecting the + actually available CPUs. The ActiveProcessorCount is correct + though. So we just use ActiveProcessorCount for now, hoping for + the best. */ + num_cpu_per_group + = plpi->Group.GroupInfo[0].ActiveProcessorCount; + break; + } + + return num_cpu_per_group; +} diff --git a/winsup/cygwin/miscfuncs.h b/winsup/cygwin/miscfuncs.h index 8ad9643a3..b983e6d81 100644 --- a/winsup/cygwin/miscfuncs.h +++ b/winsup/cygwin/miscfuncs.h @@ -119,4 +119,6 @@ extern "C" HANDLE WINAPI CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func, void SetThreadName (DWORD dwThreadID, const char* threadName); +WORD __get_cpus_per_group (void); + #endif /*_MISCFUNCS_H*/ diff --git a/winsup/cygwin/release/2.11.0 b/winsup/cygwin/release/2.11.0 index 2a90b1f6f..3ed196570 100644 --- a/winsup/cygwin/release/2.11.0 +++ b/winsup/cygwin/release/2.11.0 @@ -1,7 +1,8 @@ What's new: ----------- -- New API: clearenv, pthread_tryjoin_np, pthread_timedjoin_np. +- New APIs: clearenv, pthread_tryjoin_np, pthread_timedjoin_np, + sched_getcpu. - New APIs: aio_cancel, aio_error, aio_fsync, aio_read, aio_return, aio_suspend, aio_write, lio_listio. diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc index a32e9424d..702d038b0 100644 --- a/winsup/cygwin/sched.cc +++ b/winsup/cygwin/sched.cc @@ -411,4 +411,17 @@ sched_yield () SwitchToThread (); return 0; } + +int +sched_getcpu () +{ + if (!wincap.has_processor_groups ()) + return (int) GetCurrentProcessorNumber (); + + PROCESSOR_NUMBER pnum; + + GetCurrentProcessorNumberEx (&pnum); + return pnum.Group * __get_cpus_per_group () + pnum.Number; } + +} /* extern C */ diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml index 873a579a2..63cb0ba36 100644 --- a/winsup/doc/new-features.xml +++ b/winsup/doc/new-features.xml @@ -17,7 +17,7 @@ SO_RCVTIMEO and SO_SNDTIMEO socket options are now honored. -New API: clearenv, pthread_tryjoin_np, pthread_timedjoin_np. +New APIs: clearenv, pthread_tryjoin_np, pthread_timedjoin_np, sched_getcpu. diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml index 9cb55ca56..afa1ca409 100644 --- a/winsup/doc/posix.xml +++ b/winsup/doc/posix.xml @@ -1375,6 +1375,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008). rawmemchr removexattr scandirat + sched_getcpu setxattr sincos sincosf