[prev in list] [next in list] [prev in thread] [next in thread] 

List:       wine-patches
Subject:    Implement SetThreadPriority
From:       Chris Robinson <chris.kcat () gmail ! com>
Date:       2006-07-31 22:28:01
Message-ID: 200607311528.01213.chris.kcat () gmail ! com
[Download RAW message or body]

This is a modified patch from Mike Hearn's previous attempt (which can be 
found on the wiki). The changes are that it doesn't play with libcap and root 
capabilities to encourage root usage (setting a non-zero RLIMIT_RTPRIO value 
for 2.6.12 or newer Linux kernels is enough), and it uses the 
sched_get_priority_min function instead of the hardcoded 0 and 1 priority 
values.

["wine_thread_prio.diff" (text/x-diff)]

Index: server/thread.c
===================================================================
RCS file: /home/wine/wine/server/thread.c,v
retrieving revision 1.149
diff -u -r1.149 thread.c
--- server/thread.c	26 Jul 2006 14:01:21 -0000	1.149
+++ server/thread.c	31 Jul 2006 22:17:18 -0000
@@ -32,6 +32,9 @@
 #include <sys/types.h>
 #include <unistd.h>
 #include <time.h>
+#ifdef HAVE_SCHED_H
+#include <sched.h>
+#endif
 #ifdef HAVE_POLL_H
 #include <poll.h>
 #endif
@@ -314,12 +317,57 @@
     return NULL;
 }
 
+static void set_thread_priority( int unix_tid, int ntprio )
+{
+#ifdef HAVE_SCHED_H    
+    struct sched_param param;
+    int result, scheduler;
+
+    assert( unix_tid != -1 );
+
+    if (ntprio == THREAD_PRIORITY_TIME_CRITICAL)
+        scheduler = SCHED_FIFO;
+    else
+        scheduler = SCHED_OTHER;
+
+    /* Use the minimum real-time priority possible for now (on Linux this
+     * should be 1 for SCHED_FIFO and 0 for SCHED_OTHER) */
+    param.sched_priority = sched_get_priority_min( scheduler );
+
+    errno = 0;
+    result = sched_setscheduler( unix_tid, scheduler, &param );
+
+    if (result != 0)
+    {
+        if (errno == EPERM)
+        {
+            static BOOL warned = FALSE;
+
+            if (!warned)
+            {
+                warned = TRUE;
+                fprintf( stderr, "\nwineserver: Failed to promote the priority of a \
time critical thread.\n" ); +                fprintf( stderr, "wineserver: Audio may \
destabilise.\n" ); +            }
+        }
+        else
+            perror( "wineserver: sched_setscheduler" );
+    }
+#endif    
+}
+
 /* 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)
+    {
+        if ((thread->priority != req->priority) && (thread->unix_tid != -1))
+            set_thread_priority( thread->unix_tid, req->priority );
+        
         thread->priority = req->priority;
+    }
+
     if (req->mask & SET_THREAD_INFO_AFFINITY)
     {
         if (req->affinity != 1) set_error( STATUS_INVALID_PARAMETER );
@@ -886,6 +934,10 @@
     }
     debug_level = max( debug_level, req->debug_level );
 
+    /* we may have raced with a SetThreadPriority call */
+    if (current->priority != THREAD_PRIORITY_NORMAL)
+        set_thread_priority( current->unix_tid, current->priority );
+    
     reply->pid     = get_process_id( process );
     reply->tid     = get_thread_id( current );
     reply->version = SERVER_PROTOCOL_VERSION;





[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic