Have sched_getaffinity() interface like glibc's, and provide an
undocumented internal interface __sched_getaffinity_sys() like the Linux
kernel's sched_getaffinity() for benefit of taskset(1).

---
 newlib/libc/include/sched.h            |  3 +++
 winsup/cygwin/common.din               |  1 +
 winsup/cygwin/include/cygwin/version.h |  2 +-
 winsup/cygwin/sched.cc                 | 29 +++++++++++++++++---------
 4 files changed, 24 insertions(+), 11 deletions(-)

diff --git a/newlib/libc/include/sched.h b/newlib/libc/include/sched.h
index fc44209d6..b6425320e 100644
--- a/newlib/libc/include/sched.h
+++ b/newlib/libc/include/sched.h
@@ -116,6 +116,9 @@ int sched_get_thread_affinity (void *, size_t, cpu_set_t *);
 int sched_setaffinity (pid_t, size_t, const cpu_set_t *);
 int sched_set_thread_affinity (void *, size_t, const cpu_set_t *);
 #endif
+#ifdef __CYGWIN__
+int __sched_getaffinity_sys (pid_t, size_t, cpu_set_t *);
+#endif
 
 #ifdef __cplusplus
 }
diff --git a/winsup/cygwin/common.din b/winsup/cygwin/common.din
index 81292ab7b..9cb67992b 100644
--- a/winsup/cygwin/common.din
+++ b/winsup/cygwin/common.din
@@ -98,6 +98,7 @@ __res_querydomain SIGFE
 __res_search SIGFE
 __res_send SIGFE
 __res_state SIGFE
+__sched_getaffinity_sys SIGFE
 __signbitd NOSIGFE
 __signbitf NOSIGFE
 __signgam NOSIGFE
diff --git a/winsup/cygwin/include/cygwin/version.h 
b/winsup/cygwin/include/cygwin/version.h
index b70b9e281..f47055d84 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -510,7 +510,7 @@ details. */
   337: MOUNT_BINARY -> MOUNT_TEXT
   338: Export secure_getenv.
   339: Export sched_getaffinity, sched_setaffinity, pthread_getaffinity_np,
-       pthread_setaffinity_np.
+       pthread_setaffinity_np, __sched_getaffinity_sys.
 
   Note that we forgot to bump the api for ualarm, strtoll, strtoull,
   sigaltstack, sethostname. */
diff --git a/winsup/cygwin/sched.cc b/winsup/cygwin/sched.cc
index e7b44d319..fdb8ba738 100644
--- a/winsup/cygwin/sched.cc
+++ b/winsup/cygwin/sched.cc
@@ -555,8 +555,9 @@ done:
 }
 
 int
-sched_getaffinity (pid_t pid, size_t sizeof_set, cpu_set_t *set)
+__sched_getaffinity_sys (pid_t pid, size_t sizeof_set, cpu_set_t *set)
 {
+  /* Emulate Linux raw sched_getaffinity syscall for benefit of taskset(1) */
   HANDLE process = 0;
   int status = 0;
 
@@ -603,14 +604,21 @@ done:
   if (status)
     {
       set_errno (status);
-      status = -1;
-    }
-  else
-    {
-      /* Emulate documented Linux kernel behavior on successful return */
-      status = wincap.cpu_count ();
+      return -1;
     }
-  return status;
+
+  /* On successful return, we would ordinarily return 0, but instead we
+     emulate the behavior of the raw sched_getaffinity syscall on Linux. */
+  return min (sizeof_set, sizeof (cpu_set_t));
+}
+
+int
+sched_getaffinity (pid_t pid, size_t sizeof_set, cpu_set_t *set)
+{
+  /* Emulate the Linux glibc interface of sched_getaffinity() by calling
+     the raw syscall emulation and mapping positive results to 0. */
+  int status = __sched_getaffinity_sys (pid, sizeof_set, set);
+  return status > 0 ? 0 : status;
 }
 
 int
@@ -727,9 +735,10 @@ done:
   if (status)
     {
       set_errno (status);
-      status = -1;
+      return -1;
     }
-  return status;
+
+  return 0;
 }
 
 } /* extern C */
-- 
2.21.0

Reply via email to