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 <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2018-08-07 14:51:10 +02:00
parent c233d42264
commit 1e0a1f59d9
10 changed files with 77 additions and 44 deletions

View File

@ -580,6 +580,7 @@ LoadDLLfunc (if_indextoname, 8, iphlpapi)
LoadDLLfunc (if_nametoindex, 4, iphlpapi) LoadDLLfunc (if_nametoindex, 4, iphlpapi)
LoadDLLfuncEx2 (DiscardVirtualMemory, 8, kernel32, 1, 127) LoadDLLfuncEx2 (DiscardVirtualMemory, 8, kernel32, 1, 127)
LoadDLLfunc (GetCurrentProcessorNumberEx, 4, kernel32)
LoadDLLfuncEx (GetLogicalProcessorInformationEx, 12, kernel32, 1) LoadDLLfuncEx (GetLogicalProcessorInformationEx, 12, kernel32, 1)
LoadDLLfunc (GetSystemTimePreciseAsFileTime, 4, kernel32) LoadDLLfunc (GetSystemTimePreciseAsFileTime, 4, kernel32)
LoadDLLfuncEx (PrefetchVirtualMemory, 16, kernel32, 1) LoadDLLfuncEx (PrefetchVirtualMemory, 16, kernel32, 1)

View File

@ -1249,6 +1249,7 @@ scandirat SIGFE
scanf SIGFE scanf SIGFE
sched_get_priority_max SIGFE sched_get_priority_max SIGFE
sched_get_priority_min SIGFE sched_get_priority_min SIGFE
sched_getcpu SIGFE
sched_getparam SIGFE sched_getparam SIGFE
sched_getscheduler NOSIGFE sched_getscheduler NOSIGFE
sched_rr_get_interval SIGFE sched_rr_get_interval SIGFE

View File

@ -600,7 +600,6 @@ format_proc_stat (void *, char *&destbuf)
return eobuf - buf; return eobuf - buf;
} }
#define add_size(p,s) ((p) = ((__typeof__(p))((PBYTE)(p)+(s))))
#define print(x) { bufptr = stpcpy (bufptr, (x)); } #define print(x) { bufptr = stpcpy (bufptr, (x)); }
static inline uint32_t static inline uint32_t
@ -640,46 +639,7 @@ format_proc_cpuinfo (void *, char *&destbuf)
char *bufptr = buf; char *bufptr = buf;
//WORD num_cpu_groups = 1; /* Pre Windows 7, only one group... */ //WORD num_cpu_groups = 1; /* Pre Windows 7, only one group... */
WORD num_cpu_per_group = 64; /* ...and a max of 64 CPUs. */ WORD num_cpu_per_group = __get_cpus_per_group ();
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;
}
cpu_num_p = wcpcpy (cpu_key, L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION" cpu_num_p = wcpcpy (cpu_key, L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION"
"\\System\\CentralProcessor\\"); "\\System\\CentralProcessor\\");

View File

@ -498,12 +498,13 @@ details. */
327: Export pthread_tryjoin_np, pthread_timedjoin_np. 327: Export pthread_tryjoin_np, pthread_timedjoin_np.
328: Export aio_cancel, aio_error, aio_fsync, aio_read, aio_return, 328: Export aio_cancel, aio_error, aio_fsync, aio_read, aio_return,
aio_suspend, aio_write, lio_listio. aio_suspend, aio_write, lio_listio.
329: Export sched_getcpu..
Note that we forgot to bump the api for ualarm, strtoll, strtoull, Note that we forgot to bump the api for ualarm, strtoll, strtoull,
sigaltstack, sethostname. */ sigaltstack, sethostname. */
#define CYGWIN_VERSION_API_MAJOR 0 #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 /* There is also a compatibity version number associated with the shared memory
regions. It is incremented when incompatible changes are made to the shared regions. It is incremented when incompatible changes are made to the shared

View File

@ -15,6 +15,7 @@ details. */
#include "path.h" #include "path.h"
#include "fhandler.h" #include "fhandler.h"
#include "exception.h" #include "exception.h"
#include "tls_pbuf.h"
int __reg2 int __reg2
check_invalid_virtual_addr (const void *s, unsigned sz) check_invalid_virtual_addr (const void *s, unsigned sz)
@ -959,3 +960,55 @@ SetThreadName(DWORD dwThreadID, const char* threadName)
__except (NO_ERROR) __except (NO_ERROR)
__endtry __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;
}

View File

@ -119,4 +119,6 @@ extern "C" HANDLE WINAPI CygwinCreateThread (LPTHREAD_START_ROUTINE thread_func,
void SetThreadName (DWORD dwThreadID, const char* threadName); void SetThreadName (DWORD dwThreadID, const char* threadName);
WORD __get_cpus_per_group (void);
#endif /*_MISCFUNCS_H*/ #endif /*_MISCFUNCS_H*/

View File

@ -1,7 +1,8 @@
What's new: 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, - New APIs: aio_cancel, aio_error, aio_fsync, aio_read, aio_return,
aio_suspend, aio_write, lio_listio. aio_suspend, aio_write, lio_listio.

View File

@ -411,4 +411,17 @@ sched_yield ()
SwitchToThread (); SwitchToThread ();
return 0; 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 */

View File

@ -17,7 +17,7 @@ SO_RCVTIMEO and SO_SNDTIMEO socket options are now honored.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>
New API: clearenv, pthread_tryjoin_np, pthread_timedjoin_np. New APIs: clearenv, pthread_tryjoin_np, pthread_timedjoin_np, sched_getcpu.
</para></listitem> </para></listitem>
<listitem><para> <listitem><para>

View File

@ -1375,6 +1375,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para>
rawmemchr rawmemchr
removexattr removexattr
scandirat scandirat
sched_getcpu
setxattr setxattr
sincos sincos
sincosf sincosf