SetThreadPriority, gamerz needed (Re: Game sound problem with wine 20050310 (Debian testing))

Andreas Mohr andi at
Sun May 15 16:32:58 CDT 2005


On Sat, May 07, 2005 at 12:13:00PM +0100, J. Grant wrote:
> On 07/05/05 10:49, Andreas Mohr wrote:

> Okay, great! I am running debian sarge 2.6.8-2-k7 kernel, not 
> sure if that is SCHED_ISO and SCHED_BATCH aware, but I can 
> upgrade to the latest kernel in debian testing/sarge if necessary.
Haha, good joke. That stuff will require a REAL self-made kernel,
a -ck one with that improved scheduling and much better
interactivity, probably best to grab the 2.6.11-ck8 patch version,

(normal kernels don't have non-root realtime scheduling, due to very
tricky implementation of usually easily DoS-able realtime priorities)

> Hopefully it would give some improvement.
You'd be able to test it now, with my very preliminary
proof-of-concept patch that is attached (it's not tested since I
currently don't know of any software/game that uses
Also, testing would best be done based on known-to-be-problematic
games. If this patch together with a SCHED_ISO-capable kernel
makes a real difference, then we have something that we should
continue to work on.

OK, again, you need:
- 2.6.X-ckX kernel (the ones with SCHED_ISO, SCHED_BATCH support)
- rather current (CVS) Wine, since it requires the SetThreadPriority
patches in various multimedia/sound threads in Wine
- my patch in that Wine
- one or better several preferrably problematic game(s) with in-game
  lags or sound distortion etc. pp.

And of course you should first run the game *without* my patch,
since the -ck kernel may very well significantly improve game
behaviour anyway (or actually deteriorate it), so the test basis
is VERY different from running a normal kernel and this should
be taken into account properly, otherwise you can just bin those
test findings. :)

I'm interested in test results from as many people as possible,
preferrably people with a good (excessive?) gaming background ;)

The best result would be to have this patch dramatically improve
lag or sound or graphics interactivity in games in a recent CVS
Wine version on a -ck kernel, compared to exactly the same
environment *minus* my SetThreadPriority() patch.

One last thing: you might have to change the unix_tid in the
patch into unix_pid in case it fails with the unmodified patch.

Please report any changes you observe.

Have fun,

Andreas Mohr
-------------- next part --------------
Determining best CVS host...
Using CVSROOT :pserver:cvs at
Index: server/thread.c
RCS file: /home/wine/wine/server/thread.c,v
retrieving revision 1.112
diff -u -r1.112 thread.c
--- server/thread.c	24 Apr 2005 17:35:52 -0000	1.112
+++ server/thread.c	15 May 2005 21:29:30 -0000
@@ -35,6 +35,7 @@
 #ifdef HAVE_POLL_H
 #include <poll.h>
+#include <sched.h>
 #include "windef.h"
 #include "winbase.h"
@@ -299,12 +300,66 @@
     return NULL;
+static inline void set_thread_priority(struct thread *thread, int priority)
+    struct sched_param parm;
+    int unix_priority = 0;
+    int unix_policy = SCHED_OTHER;
+    /* register the windows data... */
+    thread->priority = priority;
+    /* ...then try to do something useful on the Unix side */
+    switch (priority) {
+	    fprintf(stderr, "setting SCHED_BATCH idle scheduling\n");
+            unix_policy = SCHED_BATCH;
+            fprintf(stderr, "SCHED_BATCH Linux scheduling policy not available - you probably aren't running a Con Kolivas kernel...\n");
+            break;
+#ifdef SCHED_ISO
+	    fprintf(stderr, "setting SCHED_ISO real-time scheduling\n");
+            unix_policy = SCHED_ISO;
+            fprintf(stderr, "SCHED_ISO Linux scheduling policy not available - you probably aren't running a Con Kolivas kernel...\n");
+            break;
+        default:
+#if 0
+            if ((priority >= THREAD_PRIORITY_LOWEST)
+             && (priority <= THREAD_PRIORITY_HIGHEST))
+            {
+                fprintf(stderr, "not sure how to map standard priorities yet, using a best-effort implementation\n");
+                /* we can only renice to positive numbers, so... */
+                if ((priority >= THREAD_PRIORITY_LOWEST)
+                 && (priority <= 0))
+            	    unix_priority = -priority * 4; /* multiplication might be useful */
+            }
+            else
+                fprintf(stderr, "strange priority %d, ignoring!\n");
+	    /* hmm, not sure what to do here, according to
+	     * man sched_setscheduler, the nice level must be set
+	     * via setpriority */
+	    break;
+    }
+    parm.sched_priority = unix_priority;
+    /* FIXME: need to use unix_pid here instead?? */
+    if (sched_setscheduler(thread->unix_tid, unix_policy, &parm))
+	    fprintf(stderr, "sched_setscheduler() failed, errno %d\n", errno);
 /* set all information about a thread */
 static void set_thread_info( struct thread *thread,
                              const struct set_thread_info_request *req )
     if (req->mask & SET_THREAD_INFO_PRIORITY)
-        thread->priority = req->priority;
+        set_thread_priority(thread, req->priority);
     if (req->mask & SET_THREAD_INFO_AFFINITY)
         if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );

More information about the wine-devel mailing list