https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=1e0a1f59d9e64430ce796c578e0813100c0cf0d7

commit 1e0a1f59d9e64430ce796c578e0813100c0cf0d7
Author: Corinna Vinschen <cori...@vinschen.de>
Date:   Tue Aug 7 14:51:10 2018 +0200

    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 <cori...@vinschen.de>

Diff:
---
 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 199821d..f71abe8 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 312b04c..d1d9555 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 3e25bdc..c9761b5 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 5140dd1..4f90b8f 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 3ad6587..b5dfffc 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 8ad9643..b983e6d 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 2a90b1f..3ed1965 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 a32e942..702d038 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 873a579..63cb0ba 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.
 </para></listitem>
 
 <listitem><para>
-New API: clearenv, pthread_tryjoin_np, pthread_timedjoin_np.
+New APIs: clearenv, pthread_tryjoin_np, pthread_timedjoin_np, sched_getcpu.
 </para></listitem>
 
 <listitem><para>
diff --git a/winsup/doc/posix.xml b/winsup/doc/posix.xml
index 9cb55ca..afa1ca4 100644
--- a/winsup/doc/posix.xml
+++ b/winsup/doc/posix.xml
@@ -1375,6 +1375,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
     rawmemchr
     removexattr
     scandirat
+    sched_getcpu
     setxattr
     sincos
     sincosf

Reply via email to