Hi, 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, from http://members.optusnet.com.au/ckolivas/kernel/ (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 SetThreadPriority()). 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
Determining best CVS host... Using CVSROOT :pserver:[EMAIL PROTECTED]:/home/wine 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> #endif +#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) { + case THREAD_PRIORITY_IDLE: +#ifdef SCHED_BATCH + fprintf(stderr, "setting SCHED_BATCH idle scheduling\n"); + unix_policy = SCHED_BATCH; +#else + fprintf(stderr, "SCHED_BATCH Linux scheduling policy not available - you probably aren't running a Con Kolivas kernel...\n"); +#endif + break; + case THREAD_PRIORITY_TIME_CRITICAL: +#ifdef SCHED_ISO + fprintf(stderr, "setting SCHED_ISO real-time scheduling\n"); + unix_policy = SCHED_ISO; +#else + fprintf(stderr, "SCHED_ISO Linux scheduling policy not available - you probably aren't running a Con Kolivas kernel...\n"); +#endif + 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"); +#else + /* hmm, not sure what to do here, according to + * man sched_setscheduler, the nice level must be set + * via setpriority */ +#endif + 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 );