[PATCH 04/17] server: Thread prio patch based on rtkit

Maarten Lankhorst m.b.lankhorst at gmail.com
Fri Nov 20 11:14:50 CST 2009


---
 dlls/ntdll/rtkit.c  |  201 +++++++++++++++++++++++++++++++++++++++++++++++++++
 dlls/ntdll/rtkit.h  |   22 ++++++
 dlls/ntdll/sync.c   |   11 +++
 server/protocol.def |    7 ++
 server/thread.c     |   14 ++++
 5 files changed, 255 insertions(+), 0 deletions(-)
 create mode 100644 dlls/ntdll/rtkit.c
 create mode 100644 dlls/ntdll/rtkit.h

diff --git a/dlls/ntdll/rtkit.c b/dlls/ntdll/rtkit.c
new file mode 100644
index 0000000..1eb8fc3
--- /dev/null
+++ b/dlls/ntdll/rtkit.c
@@ -0,0 +1,201 @@
+/*-*- Mode: C; c-basic-offset: 8 -*-*/
+
+/***
+  Copyright 2009 Lennart Poettering
+
+  Permission is hereby granted, free of charge, to any person
+  obtaining a copy of this software and associated documentation files
+  (the "Software"), to deal in the Software without restriction,
+  including without limitation the rights to use, copy, modify, merge,
+  publish, distribute, sublicense, and/or sell copies of the Software,
+  and to permit persons to whom the Software is furnished to do so,
+  subject to the following conditions:
+
+  The above copyright notice and this permission notice shall be
+  included in all copies or substantial portions of the Software.
+
+  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+  SOFTWARE.
+***/
+
+#include "config.h"
+#include "wine/port.h"
+#include "wine/library.h"
+
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SCHED_H
+#include <sys/sched.h>
+#endif
+#include <sys/resource.h>
+#include "rtkit.h"
+
+#if defined(HAVE_SETRLIMIT) && defined(__linux__)
+
+#include <sched.h>
+#include <string.h>
+#include <unistd.h>
+#include <dbus/dbus.h>
+#include <sys/syscall.h>
+
+#ifndef RLIMIT_RTTIME
+#define RLIMIT_RTTIME 15
+#endif
+
+#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1"
+#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1"
+
+#define FUNCPTR(fn) static typeof(fn) *p ##fn
+
+FUNCPTR(dbus_error_init);
+FUNCPTR(dbus_error_free);
+FUNCPTR(dbus_bus_get);
+FUNCPTR(dbus_message_new_method_call);
+FUNCPTR(dbus_message_append_args);
+FUNCPTR(dbus_connection_send_with_reply_and_block);
+FUNCPTR(dbus_message_unref);
+FUNCPTR(dbus_set_error_from_message);
+#undef FUNCPTR
+
+static int translate_error(const char *name) {
+    if (strcmp(name, DBUS_ERROR_NO_MEMORY) == 0)
+        return -ENOMEM;
+    if (strcmp(name, DBUS_ERROR_SERVICE_UNKNOWN) == 0 ||
+        strcmp(name, DBUS_ERROR_NAME_HAS_NO_OWNER) == 0)
+        return -ENOENT;
+    if (strcmp(name, DBUS_ERROR_ACCESS_DENIED) == 0 ||
+        strcmp(name, DBUS_ERROR_AUTH_FAILED) == 0)
+        return -EACCES;
+
+    return -EIO;
+}
+
+static void init_dbus(void) {
+#define FUNCPTR(fn) p ##fn = wine_dlsym(libdbus, #fn, NULL, 0);
+    char error[512];
+    void *libdbus = wine_dlopen("libdbus-glib-1.so.2", RTLD_NOW, error, sizeof(error));
+    FUNCPTR(dbus_error_init);
+    FUNCPTR(dbus_error_free);
+    FUNCPTR(dbus_bus_get);
+    FUNCPTR(dbus_message_new_method_call);
+    FUNCPTR(dbus_message_append_args);
+    FUNCPTR(dbus_connection_send_with_reply_and_block);
+    FUNCPTR(dbus_message_unref);
+    FUNCPTR(dbus_set_error_from_message);
+#undef FUNCPTR
+}
+
+static DBusConnection *get_dbus(void) {
+    static DBusConnection *bus;
+    DBusError error;
+
+    if (bus)
+        return bus;
+    init_dbus();
+    pdbus_error_init(&error);
+
+    bus = pdbus_bus_get(DBUS_BUS_SYSTEM, &error);
+    return bus;
+}
+
+static void set_rttime_limit(void)
+{
+    struct rlimit rlimit;
+    static int set;
+
+    if (set)
+        return;
+    set = 1;
+
+    rlimit.rlim_max = 60000000ULL;
+    rlimit.rlim_cur = rlimit.rlim_max - 10000000ULL;
+    setrlimit( RLIMIT_RTTIME, &rlimit );
+}
+
+int rtkit_make_realtime(pid_t thread, int priority) {
+    DBusConnection *bus = get_dbus();
+    DBusMessage *m = NULL, *r = NULL;
+    dbus_uint64_t u64;
+    dbus_uint32_t u32;
+    DBusError error;
+    int ret;
+
+    if (!bus)
+        return -ENOTSUP;
+
+    set_rttime_limit();
+
+    pdbus_error_init(&error);
+
+    if (!(m = pdbus_message_new_method_call(
+                          RTKIT_SERVICE_NAME,
+                          RTKIT_OBJECT_PATH,
+                          "org.freedesktop.RealtimeKit1",
+                          "MakeThreadRealtime"))) {
+            ret = -ENOMEM;
+            goto finish;
+    }
+
+    u64 = (dbus_uint64_t) thread;
+    u32 = (dbus_uint32_t) priority;
+
+    if (!pdbus_message_append_args(m, DBUS_TYPE_UINT64, &u64,
+                                   DBUS_TYPE_UINT32, &u32,
+                                   DBUS_TYPE_INVALID)) {
+        ret = -ENOMEM;
+        goto finish;
+    }
+
+    if (!(r = pdbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
+        ret = translate_error(error.name);
+        goto finish;
+    }
+
+
+    if (pdbus_set_error_from_message(&error, r)) {
+        ret = translate_error(error.name);
+        goto finish;
+    }
+
+    ret = 0;
+
+finish:
+
+    if (m)
+        pdbus_message_unref(m);
+
+    if (r)
+        pdbus_message_unref(r);
+
+    pdbus_error_free(&error);
+
+    return ret;
+}
+
+int rtkit_undo_realtime(pid_t thread) {
+    struct sched_param parm;
+    int ret;
+    memset(&parm, 0, sizeof(parm));
+    ret = sched_setscheduler(thread, SCHED_OTHER, &parm);
+    if (ret < 0)
+        return -errno;
+    return ret;
+}
+
+#else
+
+int rtkit_make_realtime(pid_t thread, int priority) {
+        return -ENOTSUP;
+}
+
+int rtkit_undo_realtime(pid_t thread) {
+        return -ENOTSUP;
+}
+
+#endif
diff --git a/dlls/ntdll/rtkit.h b/dlls/ntdll/rtkit.h
new file mode 100644
index 0000000..e84227e
--- /dev/null
+++ b/dlls/ntdll/rtkit.h
@@ -0,0 +1,22 @@
+/*
+ * realtime kit interface
+ *
+ * Copyright (C) 2010 Maarten Lankhorst
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+extern int rtkit_make_realtime(pid_t tid, int prio);
+extern int rtkit_undo_realtime(pid_t tid);
diff --git a/dlls/ntdll/sync.c b/dlls/ntdll/sync.c
index 3e27d09..6318c6e 100644
--- a/dlls/ntdll/sync.c
+++ b/dlls/ntdll/sync.c
@@ -35,6 +35,7 @@
 #ifdef HAVE_SYS_POLL_H
 # include <sys/poll.h>
 #endif
+#include <sys/types.h>
 #ifdef HAVE_UNISTD_H
 # include <unistd.h>
 #endif
@@ -51,6 +52,7 @@
 #define NONAMELESSSTRUCT
 
 #include "ntstatus.h"
+#include "rtkit.h"
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winternl.h"
@@ -878,6 +880,15 @@ static BOOL invoke_apc( const apc_call_t *call, apc_result_t *result )
         }
         break;
     }
+    case APC_SET_RT:
+    {
+        int ret;
+        if (call->setrt.rt)
+            ret = rtkit_make_realtime(call->setrt.tid, 1);
+        else
+            ret = rtkit_undo_realtime(call->setrt.tid);
+        FIXME("setrt(%i) on %i returns %i\n", call->setrt.rt, call->setrt.tid, ret);
+    }
     case APC_VIRTUAL_ALLOC:
         result->type = call->type;
         addr = wine_server_get_ptr( call->virtual_alloc.addr );
diff --git a/server/protocol.def b/server/protocol.def
index 4aaff10..0c97021 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -373,6 +373,7 @@ enum apc_type
     APC_USER,
     APC_TIMER,
     APC_ASYNC_IO,
+    APC_SET_RT,
     APC_VIRTUAL_ALLOC,
     APC_VIRTUAL_FREE,
     APC_VIRTUAL_QUERY,
@@ -413,6 +414,12 @@ typedef union
     } async_io;
     struct
     {
+        enum apc_type    type;     /* APC_SET_RT */
+        int              rt;       /* should set or remove rt? */
+        thread_id_t      tid;      /* unix tid for thread */
+    } setrt;
+    struct
+    {
         enum apc_type    type;      /* APC_VIRTUAL_ALLOC */
         unsigned int     op_type;   /* type of operation */
         client_ptr_t     addr;      /* requested address */
diff --git a/server/thread.c b/server/thread.c
index a6bc55a..fd7dbf0 100644
--- a/server/thread.c
+++ b/server/thread.c
@@ -439,6 +439,16 @@ int set_thread_affinity( struct thread *thread, affinity_t affinity )
 #define THREAD_PRIORITY_REALTIME_HIGHEST 6
 #define THREAD_PRIORITY_REALTIME_LOWEST -7
 
+static void set_thread_priority( struct thread *thread, int ntprio )
+{
+    apc_call_t data;
+    data.type = APC_SET_RT;
+    data.setrt.rt = (ntprio == THREAD_PRIORITY_TIME_CRITICAL);
+    data.setrt.tid = thread->unix_tid;
+
+    thread_queue_apc( thread, NULL, &data );
+}
+
 /* set all information about a thread */
 static void set_thread_info( struct thread *thread,
                              const struct set_thread_info_request *req )
@@ -455,7 +465,11 @@ static void set_thread_info( struct thread *thread,
         if ((req->priority >= min && req->priority <= max) ||
             req->priority == THREAD_PRIORITY_IDLE ||
             req->priority == THREAD_PRIORITY_TIME_CRITICAL)
+        {
+            if ((thread->priority != req->priority) && (thread->unix_tid != -1))
+                set_thread_priority( thread, req->priority );
             thread->priority = req->priority;
+        }
         else
             set_error( STATUS_INVALID_PARAMETER );
     }
-- 
1.7.0


--------------010002070803070801090908--



More information about the wine-devel mailing list