We support pthread_getaffinity_np() on other threads, not just on the
current thread.  This patch adds this support also for sched_getaffinity().

Since both functions behave almost the same, the patch creates a single
function which both of them will call. Note how the return values differ,
though: pthread_getaffinity_np() follows pthread tradition and returns
errors directly, while sched_getaffinity() follows Unix tradition and
returns errors in errno.

Fixes #776.

Signed-off-by: Nadav Har'El <[email protected]>
---
 libc/pthread.cc | 49 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 35 insertions(+), 14 deletions(-)

diff --git a/libc/pthread.cc b/libc/pthread.cc
index 1675ce9..631eb08 100644
--- a/libc/pthread.cc
+++ b/libc/pthread.cc
@@ -998,26 +998,57 @@ int sched_setaffinity(pid_t pid, size_t cpusetsize,
     return 0;
 }
 
-int pthread_getaffinity_np(const pthread_t thread, size_t cpusetsize,
+static int getaffinity(const sched::thread *t, size_t cpusetsize,
         cpu_set_t *cpuset)
 {
     if (sched::cpus.size() > cpusetsize * 8) {
         // not enough room in cpuset
         return EINVAL;
     }
-    sched::thread &t = pthread::from_libc(thread)->_thread;
     // Currently OSv does not have a real notion of a list of allowable
     // CPUs for a thread, as Linux does, but we have the notion of pinning
     // the thread to a single CPU. Note that if the CPU is only temporarily
     // bound to a CPU with a migration_lock (e.g., while accessing a per-cpu
     // variable), it is not considered pinned.
     memset(cpuset, 0, cpusetsize);
-    if (!t.pinned()) {
+    if (!t->pinned()) {
         for (unsigned i = 0; i < sched::cpus.size(); i++) {
             CPU_SET(i, cpuset);
         }
     } else {
-        CPU_SET(t.tcpu()->id, cpuset);
+        CPU_SET(t->tcpu()->id, cpuset);
+    }
+    return 0;
+}
+
+int pthread_getaffinity_np(const pthread_t thread, size_t cpusetsize,
+        cpu_set_t *cpuset)
+{
+    const sched::thread *t = &pthread::from_libc(thread)->_thread;
+    return getaffinity(t, cpusetsize, cpuset);
+}
+
+int sched_getaffinity(pid_t pid, size_t cpusetsize,
+        cpu_set_t *cpuset)
+{
+    sched::thread *t;
+    if (pid == 0) {
+        t = sched::thread::current();
+    } else {
+        t = sched::thread::find_by_id(pid);
+        if (!t) {
+            errno = ESRCH;
+            return -1;
+        }
+        // TODO: After the thread was found, if it exits the code below
+        // may crash. Perhaps we should have a version of find_by_id(),
+        // with_thread_by_id(pid, func), which holds thread_map_mutex while
+        // func runs.
+    }
+    int err = getaffinity(t, cpusetsize, cpuset);
+    if (err) {
+        errno = err;
+        return -1;
     }
     return 0;
 }
@@ -1042,13 +1073,3 @@ int pthread_attr_getaffinity_np(const pthread_attr_t 
*attr, size_t cpusetsize,
 
     return 0;
 }
-
-int sched_getaffinity(pid_t pid, size_t cpusetsize,
-        cpu_set_t *cpuset)
-{
-    if (pid != 0 && (unsigned int)pid != sched::thread::current()->id()) {
-        WARN_STUBBED();
-        return EINVAL;
-    }
-    return pthread_getaffinity_np(pthread_self(), cpusetsize, cpuset);
-}
-- 
2.5.5

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to