[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