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:
		| @@ -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) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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\\"); | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -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*/ | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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 */ | ||||
|   | ||||
| @@ -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> | ||||
|   | ||||
| @@ -1375,6 +1375,7 @@ also IEEE Std 1003.1-2008 (POSIX.1-2008).</para> | ||||
|     rawmemchr | ||||
|     removexattr | ||||
|     scandirat | ||||
|     sched_getcpu | ||||
|     setxattr | ||||
|     sincos | ||||
|     sincosf | ||||
|   | ||||
		Reference in New Issue
	
	Block a user