Hi Mark, On Apr 28 22:38, Mark Geisert wrote: > There are a couple of multi-group affinity operations that cannot be done > without heroic measures. Those are marked with XXX in the code. Further > discussion would be helpful to me. > > --- > newlib/libc/include/sched.h | 13 ++ > winsup/cygwin/common.din | 4 + > winsup/cygwin/include/pthread.h | 2 + > winsup/cygwin/sched.cc | 237 ++++++++++++++++++++++++++++++++ > winsup/cygwin/thread.cc | 19 +++ > 5 files changed, 275 insertions(+) > > diff --git a/newlib/libc/include/sched.h b/newlib/libc/include/sched.h > index 1016235bb..a4d3fea6a 100644 > --- a/newlib/libc/include/sched.h > +++ b/newlib/libc/include/sched.h > @@ -92,6 +92,19 @@ int sched_yield( void ); > > #if __GNU_VISIBLE > int sched_getcpu(void); > + > +#ifdef __CYGWIN__
I don't think we really need that extra ifdef. #if __GNU_VISIBLE bracketing is sufficient. > +static int > +whichgroup (size_t sizeof_set, const cpu_set_t *set) > +{ > + //XXX code assumes __get_cpus_per_group() is fixed at 64 I don't understand this comment. It could also return 48 or 36 or any other value <= 64. Care to explain? Oh and please keep in mind that 32 bit systems only support 32 CPUs, not 64 (sizeof(KAFFINITY) == 4 on 32 bit). I don't think this has much influence on the code, if any, but it might be worthwhile to check the code on any assumptions about the size of the affinity mask. > + // There is no GetThreadAffinityMask() function, so simulate one by > + // iterating through CPUs trying to set affinity, which returns the > + // previous affinity. On success, restore original affinity. > + // This strategy is due to Damon on StackOverflow. Can you please use /* ... */ style comments? // style comments should only be used for short, single-line comments after an expression. Also, while there's no GetThreadAffinityMask() function, there is an equivalent NT level function which allows to fetch the thread affinity without having to manipulate it: THREAD_BASIC_INFORMATION tbi; KAFFINITY affinity_mask; NtQueryInformationThread (thread_handle, ThreadBasicInformation, &tbi, sizeof tbi, NULL); affinity_mask = tbi.AffinityMask; All required definitions already exist in ntdll.h and are used in fhandler_process.cc, just for another purpose. > +int > +sched_getaffinity (pid_t pid, size_t sizeof_set, cpu_set_t *set) > +{ > + HANDLE process = 0; > + int status = 0; > + > + //XXX code assumes __get_cpus_per_group() is fixed at 64 > + pinfo p (pid ? pid : getpid ()); > + if (p) > + { > + process = pid && pid != myself->pid ? > + OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, > + p->dwProcessId) : GetCurrentProcess (); > + KAFFINITY procmask; > + KAFFINITY sysmask; > + > + if (!GetProcessAffinityMask (process, &procmask, &sysmask)) > + { > +oops: > + status = geterrno_from_win_error (GetLastError (), EPERM); > + goto done; > + } > + memset (set, 0, sizeof_set); > + if (wincap.has_processor_groups ()) > + { > + USHORT groupcount = CPU_GROUPMAX; > + USHORT grouparray[CPU_GROUPMAX]; > + > + if (!GetProcessGroupAffinity (process, &groupcount, grouparray)) > + goto oops; Uhm... that's a bit ugly, imho. Rather than just jumping wildly to another spot in the middle of the same function, create a matching label at the end of the function. Or, in a simple case like this one, just call geterrno_from_win_error here and goto done. > + if (groupcount == 1) > + set[grouparray[0]] = procmask; > + else > + status = ENOSYS;//XXX multi-group code TBD... > + // There is no way to assemble the complete process affinity mask > + // without querying at least one thread per group in grouparray, > + // and we don't know which group a thread is in without querying > + // it, so must query all threads. I'd call that a heroic measure. I don't understand. GetProcessAffinityMask() exists. Am I missing something? Also, if you don't like GetProcessAffinityMask(), there's an equivalent NT function to NtQueryInformationThread: PROCESS_BASIC_INFORMATION pbi; KAFFINITY affinity_mask; NtQueryInformationProcess (process_handle, ProcessBasicInformation, &pbi, sizeof pbi, NULL); affinity_mask = pbi.AffinityMask; > + } > + else > + set[0] = procmask; > + } > + else > + status = ESRCH; > + > +done: > + if (process && process != GetCurrentProcess ()) > + CloseHandle (process); > + > + return status; > +} > +[...] Other than that, the code looks good to me. Thanks, Corinna -- Corinna Vinschen Cygwin Maintainer
signature.asc
Description: PGP signature