Due to deficient testing, the current code doesn't return a valid result to users of sched_getaffinity(). The updated code carries the determined procmask through to the generation of result cpu mask.
Recognize Windows' limitation that if the process is multi-group (i.e., has threads in multiple cpu groups) there is no visibility to which processors in other groups are being used. One could remedy this by looping through all the process' threads, but that could be expensive so is left for future contemplation. In addition, we'd have to maintain our own copy of each thread's current group and mask in internal overhead. (By the way, multi-group processes are only possible on Windows systems with more than 64 hardware threads.) A release note for 3.6.0 is included. Reported-by: Christian Franke <christian.fra...@t-online.de> Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257616.html Signed-off-by: Mark Geisert <m...@maxrnd.com> Fixes: 641ecb07533e ("Cygwin: Implement sched_[gs]etaffinity()") --- winsup/cygwin/release/3.6.0 | 4 ++++ winsup/cygwin/sched.cc | 11 +++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/winsup/cygwin/release/3.6.0 b/winsup/cygwin/release/3.6.0 index d48ee114d..ad4a6f5dc 100644 --- a/winsup/cygwin/release/3.6.0 +++ b/winsup/cygwin/release/3.6.0 @@ -132,3 +132,7 @@ Fixes: - Fix starving of auxiliary signal return address stack in case signal handlers bail out (longjmp/setcontext). Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257648.html + +- Fix sched_getaffinity(2) to carry determined process affinity all the way + through to the returned result. + Addresses: https://cygwin.com/pipermail/cygwin/2025-March/257616.html diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc index 2f4fbc31a..e15daad26 100644 --- a/winsup/cygwin/sched.cc +++ b/winsup/cygwin/sched.cc @@ -587,9 +587,16 @@ __sched_getaffinity_sys (pid_t pid, size_t sizeof_set, cpu_set_t *set) goto done; } - KAFFINITY miscmask = groupmask (__get_cpus_per_group ()); + KAFFINITY fullmask = groupmask (__get_cpus_per_group ()); + /* if process is multi-group, we don't have processor visibility. */ + /*TODO We could provide the missing Windows visibility by book-keeping + each thread's current group and mask in our thread overhead, updating + them on sched_set_thread_affinity() calls. We could then assemble the + total mask here by looping through all threads. */ + if (groupcount > 1) + procmask = fullmask; for (int i = 0; i < groupcount; i++) - setgroup (sizeof_set, set, grouparray[i], miscmask); + setgroup (sizeof_set, set, grouparray[i], fullmask & procmask); } else status = ESRCH; -- 2.45.1