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