Discussion:
[newlib-cygwin] Cygwin: implement sched_getcpu
Corinna Vinschen
2018-08-07 12:53:11 UTC
Permalink
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=1e0a1f59d9e64430ce796c578e0813100c0cf0d7

commit 1e0a1f59d9e64430ce796c578e0813100c0cf0d7
Author: Corinna Vinschen <***@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 <***@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

Loading...