server: Use kernel support for thread affinity when available

Juan Lang juan.lang at gmail.com
Thu Sep 10 11:43:02 CDT 2009


Fixes bug 19982.
--Juan
-------------- next part --------------
From 38edcb965d5f6c40e2f66c89466833e6f4cbb31d Mon Sep 17 00:00:00 2001
From: Juan Lang <juan.lang at gmail.com>
Date: Thu, 10 Sep 2009 09:38:53 -0700
Subject: [PATCH 5/5] Use kernel support for thread affinity when available

---
 configure.ac        |   11 +++++++++
 include/config.h.in |    3 ++
 server/thread.c     |   59 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 72 insertions(+), 1 deletions(-)

diff --git a/configure.ac b/configure.ac
index ac5a861..f22a507 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1791,6 +1791,17 @@ then
   AC_DEFINE(HAVE_ONE_ARG_MKDIR, 1, [Define if mkdir takes only one argument])
 fi
 
+AC_CACHE_CHECK([whether we have sched_getaffinity],
+	wine_cv_sched_getaffinity,
+	AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <unistd.h>
+#define __USE_GNU
+#include <sched.h>]],[[(void)sched_getaffinity;]])],
+		          [wine_cv_sched_getaffinity=yes],[wine_cv_sched_getaffinity=no]))
+if test "$wine_cv_sched_getaffinity" = "yes"
+then
+  AC_DEFINE(HAVE_SCHED_GETAFFINITY, 1, [Define if sched_getaffinity is present])
+fi
+
 dnl **** Check for types ****
 
 AC_C_CONST
diff --git a/include/config.h.in b/include/config.h.in
index d072380..5560f5f 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -645,6 +645,9 @@
 /* Define to 1 if you have the <sched.h> header file. */
 #undef HAVE_SCHED_H
 
+/* Define to 1 if you have the `sched_getaffinity' function. */
+#undef HAVE_SCHED_GETAFFINITY
+
 /* Define to 1 if you have the `sched_yield' function. */
 #undef HAVE_SCHED_YIELD
 
diff --git a/server/thread.c b/server/thread.c
index 2ea8929..05e150e 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -35,6 +35,10 @@
 #ifdef HAVE_POLL_H
 #include <poll.h>
 #endif
+#ifdef HAVE_SCHED_GET_AFFINITY
+#define __USE_GNU
+#include <sched.h>
+#endif
 
 #include "ntstatus.h"
 #define WIN32_NO_STATUS
@@ -404,6 +408,33 @@ struct thread *get_thread_from_pid( int pid )
     return NULL;
 }
 
+static void set_thread_affinity(struct thread *thread, affinity_t affinity)
+{
+#ifdef HAVE_SCHED_GETAFFINITY
+    if (thread->unix_pid != -1)
+    {
+        cpu_set_t set;
+        int i;
+        affinity_t mask;
+
+        CPU_ZERO( &set );
+        for (i = 0, mask = 1; mask; i++, mask <<= 1)
+            if (affinity & mask)
+                CPU_SET( i, &set );
+        if (!sched_setaffinity( thread->unix_pid, sizeof(set), &set ))
+            thread->affinity = affinity;
+        else if (errno == EPERM)
+            set_error( STATUS_ACCESS_DENIED );
+        else
+            set_error( STATUS_INVALID_PARAMETER );
+    }
+    else
+        set_error( STATUS_INVALID_HANDLE );
+#else
+    thread->affinity = affinity;
+#endif
+}
+
 #define THREAD_PRIORITY_REALTIME_HIGHEST 6
 #define THREAD_PRIORITY_REALTIME_LOWEST -7
 
@@ -428,7 +459,7 @@ static void set_thread_info( struct thread *thread,
             set_error( STATUS_INVALID_PARAMETER );
     }
     if (req->mask & SET_THREAD_INFO_AFFINITY)
-        thread->affinity = req->affinity;
+        set_thread_affinity( thread, req->affinity );
     if (req->mask & SET_THREAD_INFO_TOKEN)
         security_set_thread_token( thread, req->token );
 }
@@ -1064,6 +1095,31 @@ DECL_HANDLER(new_thread)
     }
 }
 
+static void get_thread_affinity( struct thread *thread )
+{
+    affinity_t affinity = ~0;
+
+#ifdef HAVE_SCHED_GETAFFINITY
+    if (thread->unix_pid != -1)
+    {
+        cpu_set_t set;
+
+        CPU_ZERO( &set );
+        if (!sched_getaffinity( thread->unix_pid, sizeof(set), &set ))
+        {
+            int i;
+            affinity_t mask;
+
+            affinity = 0;
+            for (i = 0, mask = 1; mask; i++, mask <<= 1)
+                if (CPU_ISSET( i, &set ))
+                    affinity |= mask;
+        }
+    }
+#endif
+    thread->affinity = affinity;
+}
+
 /* initialize a new thread */
 DECL_HANDLER(init_thread)
 {
@@ -1100,6 +1156,7 @@ DECL_HANDLER(init_thread)
     current->unix_pid = req->unix_pid;
     current->unix_tid = req->unix_tid;
     current->teb      = req->teb;
+    get_thread_affinity( current );
 
     if (!process->peb)  /* first thread, initialize the process too */
     {
-- 
1.6.3.2


More information about the wine-patches mailing list