Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- configure | 10 +++- configure.ac | 2 +- include/config.h.in | 3 + server/Makefile.in | 3 +- server/thread.c | 135 +++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 148 insertions(+), 5 deletions(-)
diff --git a/configure b/configure index e89be467e2e..f9df2f55c69 100755 --- a/configure +++ b/configure @@ -13172,9 +13172,14 @@ $as_echo "$as_me:${as_lineno-$LINENO}: dbus-1 cflags: $DBUS_CFLAGS" >&5 $as_echo "$as_me:${as_lineno-$LINENO}: dbus-1 libs: $DBUS_LIBS" >&5 ac_save_CPPFLAGS=$CPPFLAGS CPPFLAGS="$CPPFLAGS $DBUS_CFLAGS" -ac_fn_c_check_header_mongrel "$LINENO" "dbus/dbus.h" "ac_cv_header_dbus_dbus_h" "$ac_includes_default" +for ac_header in dbus/dbus.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "dbus/dbus.h" "ac_cv_header_dbus_dbus_h" "$ac_includes_default" if test "x$ac_cv_header_dbus_dbus_h" = xyes; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -ldbus-1" >&5 + cat >>confdefs.h <<_ACEOF +#define HAVE_DBUS_DBUS_H 1 +_ACEOF + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -ldbus-1" >&5 $as_echo_n "checking for -ldbus-1... " >&6; } if ${ac_cv_lib_soname_dbus_1+:} false; then : $as_echo_n "(cached) " >&6 @@ -13233,6 +13238,7 @@ else DBUS_CFLAGS="" fi
+done
CPPFLAGS=$ac_save_CPPFLAGS test -z "$DBUS_CFLAGS" || DBUS_CFLAGS=`echo " $DBUS_CFLAGS" | sed 's/ -I([^/])/ -I$(top_builddir)/\1/g'` diff --git a/configure.ac b/configure.ac index 4a3ff36e6b7..71d6da3537d 100644 --- a/configure.ac +++ b/configure.ac @@ -1386,7 +1386,7 @@ dnl **** Check for libdbus **** if test "x$with_dbus" != "xno" then WINE_PACKAGE_FLAGS(DBUS,[dbus-1],,,, - [AC_CHECK_HEADER([dbus/dbus.h], + [AC_CHECK_HEADERS([dbus/dbus.h], [WINE_CHECK_SONAME(dbus-1, dbus_connection_close,,[DBUS_CFLAGS=""],[$DBUS_LIBS])], [DBUS_CFLAGS=""])]) fi diff --git a/include/config.h.in b/include/config.h.in index 1acc02b7173..6c279f932cf 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -97,6 +97,9 @@ /* Define to 1 if you have the <curses.h> header file. */ #undef HAVE_CURSES_H
+/* Define to 1 if you have the <dbus/dbus.h> header file. */ +#undef HAVE_DBUS_DBUS_H + /* Define to 1 if you have the <dirent.h> header file. */ #undef HAVE_DIRENT_H
diff --git a/server/Makefile.in b/server/Makefile.in index b39bd30305b..114df2a8de3 100644 --- a/server/Makefile.in +++ b/server/Makefile.in @@ -50,4 +50,5 @@ MANPAGES = \ wineserver.fr.UTF-8.man.in \ wineserver.man.in
-EXTRALIBS = $(LDEXECFLAGS) -lwine $(POLL_LIBS) $(RT_LIBS) $(INOTIFY_LIBS) +EXTRAINCL = $(DBUS_CFLAGS) +EXTRALIBS = $(LDEXECFLAGS) -lwine $(POLL_LIBS) $(RT_LIBS) $(INOTIFY_LIBS) $(DBUS_LIBS) diff --git a/server/thread.c b/server/thread.c index 5b5f3cde617..77a01b1e693 100644 --- a/server/thread.c +++ b/server/thread.c @@ -58,6 +58,128 @@ #include "user.h" #include "security.h"
+#ifdef HAVE_DBUS_DBUS_H +#include <dbus/dbus.h> + +static int dbus_error_to_errno( DBusError* err ) +{ + if (!err) + return EINVAL; + if (strcmp(err->name, DBUS_ERROR_NO_MEMORY) == 0) + return ENOMEM; + if (strcmp(err->name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 || + strcmp(err->name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0) + return ENOENT; + if (strcmp(err->name, DBUS_ERROR_ACCESS_DENIED) == 0 || + strcmp(err->name, DBUS_ERROR_AUTH_FAILED) == 0) + return EACCES; + return EIO; +} + +static int rtkit_set_realtime( dbus_uint64_t process, dbus_uint64_t thread, dbus_uint32_t priority ) +{ + DBusConnection* dbus = NULL; + DBusMessage *msg = NULL, *rep = NULL; + DBusError err; + int ret = -1; + + dbus_error_init(&err); + + dbus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err)) + goto error; + + dbus_connection_set_exit_on_disconnect(dbus, 0); + + if (!(msg = dbus_message_new_method_call("org.freedesktop.RealtimeKit1", + "/org/freedesktop/RealtimeKit1", + "org.freedesktop.RealtimeKit1", + "MakeThreadRealtimeWithPID"))) + goto error; + + if (!dbus_message_append_args(msg, + DBUS_TYPE_UINT64, &process, + DBUS_TYPE_UINT64, &thread, + DBUS_TYPE_UINT32, &priority, + DBUS_TYPE_INVALID)) + goto error; + + if (!(rep = dbus_connection_send_with_reply_and_block(dbus, msg, -1, &err))) + goto error; + + if (dbus_error_is_set(&err)) + goto error; + + if (dbus_set_error_from_message(&err, rep)) + goto error; + + ret = 0; + +error: + if (ret) errno = dbus_error_to_errno(&err); + if (rep) dbus_message_unref(rep); + if (msg) dbus_message_unref(msg); + if (dbus) + { + dbus_connection_close(dbus); + dbus_connection_unref(dbus); + } + dbus_error_free(&err); + return ret; +} + +static int rtkit_set_niceness( dbus_uint64_t process, dbus_uint64_t thread, dbus_int32_t niceness ) +{ + DBusConnection* dbus = NULL; + DBusMessage *msg = NULL, *rep = NULL; + DBusError err; + int ret = -1; + + dbus_error_init(&err); + + dbus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &err); + if (dbus_error_is_set(&err)) + goto error; + + dbus_connection_set_exit_on_disconnect(dbus, 0); + + if (!(msg = dbus_message_new_method_call("org.freedesktop.RealtimeKit1", + "/org/freedesktop/RealtimeKit1", + "org.freedesktop.RealtimeKit1", + "MakeThreadHighPriorityWithPID"))) + goto error; + + if (!dbus_message_append_args(msg, + DBUS_TYPE_UINT64, &process, + DBUS_TYPE_UINT64, &thread, + DBUS_TYPE_INT32, &niceness, + DBUS_TYPE_INVALID)) + goto error; + + if (!(rep = dbus_connection_send_with_reply_and_block(dbus, msg, -1, &err))) + goto error; + + if (dbus_error_is_set(&err)) + goto error; + + if (dbus_set_error_from_message(&err, rep)) + goto error; + + ret = 0; + +error: + if (ret) errno = dbus_error_to_errno(&err); + if (rep) dbus_message_unref(rep); + if (msg) dbus_message_unref(msg); + if (dbus) + { + dbus_connection_close(dbus); + dbus_connection_unref(dbus); + } + dbus_error_free(&err); + return ret; +} +#endif
#ifdef __i386__ static const unsigned int supported_cpus = CPU_FLAG(CPU_x86); @@ -523,7 +645,8 @@ affinity_t get_thread_affinity( struct thread *thread ) return mask; }
-#if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SETPRIORITY) +#if defined(HAVE_SCHED_SETSCHEDULER) || defined(HAVE_SETPRIORITY) || \ + defined(HAVE_DBUS_DBUS_H) static int get_unix_priority( int priority_class, int priority ) { switch (priority_class) { @@ -638,6 +761,11 @@ int set_thread_priority( struct thread* thread, int priority ) param.sched_priority = get_unix_priority( thread->process->priority, priority ); if (sched_setscheduler( thread->unix_tid, SCHED_RR|SCHED_RESET_ON_FORK, ¶m ) == 0) return 0; +#endif +#ifdef HAVE_DBUS_DBUS_H + if (rtkit_set_realtime( thread->unix_pid, thread->unix_tid, + get_unix_priority( thread->process->priority, priority ) ) == 0) + return 0; #endif } else @@ -646,6 +774,11 @@ int set_thread_priority( struct thread* thread, int priority ) if (setpriority( PRIO_PROCESS, thread->unix_tid, get_unix_priority( thread->process->priority, priority ) ) == 0) return 0; +#endif +#ifdef HAVE_DBUS_DBUS_H + if (rtkit_set_niceness( thread->unix_pid, thread->unix_tid, + get_unix_priority( thread->process->priority, priority ) ) == 0) + return 0; #endif }