Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- From 1dceb627db51a239a63ed5276f7e8911be6751bc Mon Sep 17 00:00:00 2001
- From: Joakim B Hernberg <jhernberg@alchemy.lu>
- Date: Sun, 7 Nov 2010 19:10:49 +0100
- Subject: [PATCH] 3:rd wine-rt patch 101107
- ---
- README.WINE-RT | 27 +++++++++++++++++
- server/main.c | 60 ++++++++++++++++++++++++++++++++++++++
- server/thread.c | 87 ++++++++++++++++++++++++++++++++++++++++++------------
- 3 files changed, 154 insertions(+), 20 deletions(-)
- create mode 100644 README.WINE-RT
- diff --git a/README.WINE-RT b/README.WINE-RT
- new file mode 100644
- index 0000000..3f3f2c1
- --- /dev/null
- +++ b/README.WINE-RT
- @@ -0,0 +1,27 @@
- +What is it?
- +The Wine-RT patch allows programs that use windows' concept of thread priority to gain similar functionality under linux. It maps windows priority levels to linux scheduling policies. THREAD_PRIORITY_ABOVE_NORMAL, THREAD_PRIORITY_HIGHEST and THREAD_PRIORITY_TIME_CRITICAL levels which are made to run as linux SCHED_FIFO threads at priority levels that are defined by the WINERT variable. THREAD_PRIORITY_NORMAL threads are run as normal linux threads (as all threads are without the patch), and the priorities below normal (THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_LOWEST) are run as SCHED_BATCH. THREAD_PRIORITY_IDLE threads are run as SCHED_IDLE.
- +Windows' concept of priority classes is not implemented at all.
- +
- +Please note that threads running SCHED_FIFO might hang your entire system, so please exercise caution!
- +
- +How does it work?
- +When a windows program asks for a thread to be run at a higher priority, Wine will ask the linux system to schedule it as a SCHED_FIFO thread, which means that the tread will keep on executing until it has either finished, voluntarily yields execution or gets preempted by a higher priority SCHED_FIFO thread. This is already done by many linux audio applications, to ensure less xruns on lower buffer sizes. With Wine-RT, the same thing can be done for Wine applications.
- +
- +How to use it?
- +The Wine-RT functionality is not enabled by default. Instead it is controlled by 2 environment variables "WINE_RT" and "WINE_SRV_RT".
- +
- +The "WINE_RT" variable has 2 purposes, it has to be set in order to activate the patch, and it determines the priority of the SCHED_FIFO threads, Its value can be set from 1 to your system's rtprio max value minus 10, as set in limits.conf or limits.d/audio.conf. (In Debian, Ubuntu and KXStudio this value is 99). THREAD_PRIORITY_ABOVE_NORMAL threads will run at this priority level, THREAD_PRIORITY_HIGHEST threads at this level + 5, and THREAD_PRIORITY_TIME_CRITICAL threads at this level + 10.
- +
- +WINE_SRV_RT makes the wineserver main thread run SCHED_FIFO. Valid values range from 1 to your system's rtprio max value.
- +
- +We can set these variables in 2 simple ways.
- +First one is using a terminal with "exports", like this:
- +export WINE_RT=#
- +export WINE_SRV_RT=#
- +wine <app>
- +
- +or just prefix your application with 'env VARIABLE=value', like this:
- +env WINE_RT=# WINE_SRV_RT=# wine <app>
- +
- +A recommended starting point might be "env WINE_RT=15 WINE_SRV_RT=10 wine appname.exe".
- +
- diff --git a/server/main.c b/server/main.c
- index 2d841e8..a89d1e0 100644
- --- a/server/main.c
- +++ b/server/main.c
- @@ -27,10 +27,18 @@
- #include <stdio.h>
- #include <stdlib.h>
- #include <sys/time.h>
- +#include <sys/resource.h>
- +#include <sys/mman.h>
- #include <unistd.h>
- #ifdef HAVE_GETOPT_H
- # include <getopt.h>
- #endif
- +#ifdef HAVE_SCHED_H
- +#include <sched.h>
- +#ifndef SCHED_NORMAL
- +#define SCHED_NORMAL SCHED_OTHER
- +#endif
- +#endif
- #include "object.h"
- #include "file.h"
- @@ -44,6 +52,9 @@ int foreground = 0;
- timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */
- const char *server_argv0;
- +/* global variable used here and in thread.c to determine whether wine runs with rt threads and at what base value */
- +int base_rt_priority = -1;
- +
- /* parse-line args */
- static void usage(void)
- @@ -125,6 +136,51 @@ static void sigterm_handler( int signum )
- exit(1); /* make sure atexit functions get called */
- }
- +#ifdef HAVE_SCHED_H
- +void init_rt_scheduling( void )
- +{
- + struct sched_param param;
- + struct rlimit limit;
- + int priority_max, policy, wine_server_rt_priority;
- + char *enviroment, *endptr;
- +
- + getrlimit( RLIMIT_RTPRIO, &limit );
- + priority_max = limit.rlim_max;
- +
- + /* check for realtime mode and set the base priority level */
- +
- + if (!(enviroment = getenv( "WINE_RT" )))
- + return;
- + base_rt_priority = (int) strtol( enviroment, &endptr, 10 );
- + if (enviroment == endptr || base_rt_priority == 0 || base_rt_priority > priority_max - 10)
- + {
- + fprintf( stderr, "Unable to run WINE in rt mode, WINE_RT values supported on this system range from 1 to %i\n", priority_max - 10 );
- + base_rt_priority = -1;
- + return;
- + }
- + fprintf( stderr, "WINE realtime scheduling hack enabled, realtime base priority has been set to %i\n", base_rt_priority );
- +
- + /* determine scheduling policy for the main wineserver thread */
- +
- + if (!(enviroment = getenv( "WINE_SRV_RT" )))
- + {
- + fprintf( stderr, "wineserver running SCHED_NORMAL\n" );
- + return;
- + }
- + wine_server_rt_priority = (int) strtol( enviroment, &endptr, 10 );
- + if (enviroment == endptr || wine_server_rt_priority == 0 || wine_server_rt_priority > priority_max)
- + {
- + fprintf( stderr, "Unable to run the wineserver SCHED_FIFO, valid WINE_SRV_RT values range from 1 to %i\n", priority_max );
- + return;
- + }
- + fprintf( stderr, "wineserver running SCHED_FIFO at priority %i\n", wine_server_rt_priority );
- + policy = SCHED_FIFO;
- + param.sched_priority = wine_server_rt_priority;
- + if (sched_setscheduler ( 0, policy, ¶m) != 0)
- + fprintf (stderr, "Error scheduling wineserver as SCHED_FIFO\n");
- +}
- +#endif
- +
- int main( int argc, char *argv[] )
- {
- setvbuf( stderr, NULL, _IOLBF, 0 );
- @@ -138,6 +194,10 @@ int main( int argc, char *argv[] )
- signal( SIGTERM, sigterm_handler );
- signal( SIGABRT, sigterm_handler );
- +#ifdef HAVE_SCHED_H
- + init_rt_scheduling();
- +#endif
- + mlockall(MCL_FUTURE);
- sock_init();
- open_master_socket();
- diff --git a/server/thread.c b/server/thread.c
- index 05e4121..2d103b4 100644
- --- a/server/thread.c
- +++ b/server/thread.c
- @@ -32,11 +32,18 @@
- #include <sys/types.h>
- #include <unistd.h>
- #include <time.h>
- -#ifdef HAVE_POLL_H
- -#include <poll.h>
- -#endif
- #ifdef HAVE_SCHED_H
- #include <sched.h>
- +#ifndef SCHED_NORMAL
- +#define SCHED_NORMAL SCHED_OTHER
- +#endif
- +#ifndef SCHED_IDLE
- +#define SCHED_IDLE 5 /* missing from my glibc, taken from linux/sched.h */
- +#endif
- +#endif
- +
- +#ifdef HAVE_POLL_H
- +#include <poll.h>
- #endif
- #include "ntstatus.h"
- @@ -164,6 +171,8 @@ static const struct fd_ops thread_fd_ops =
- static struct list thread_list = LIST_INIT(thread_list);
- +extern int base_rt_priority;
- +
- /* initialize the structure for a newly allocated thread */
- static inline void init_thread_structure( struct thread *thread )
- {
- @@ -432,29 +441,67 @@ int set_thread_affinity( struct thread *thread, affinity_t affinity )
- return ret;
- }
- -#define THREAD_PRIORITY_REALTIME_HIGHEST 6
- -#define THREAD_PRIORITY_REALTIME_LOWEST -7
- +void set_thread_priority( struct thread *thread, int priority )
- +{
- +#ifdef HAVE_SCHED_H
- + struct sched_param param;
- + int policy;
- +
- + if (base_rt_priority == -1 || (thread->unix_tid == -1)) return;
- +
- + switch (priority)
- + {
- + case THREAD_PRIORITY_TIME_CRITICAL:
- + param.sched_priority = base_rt_priority + 10;
- + policy = SCHED_FIFO;
- + fprintf( stderr, "Thread %i at THREAD_PRIORITY_TIME_CRITICAL set to SCHED_FIFO - priority %i\n", thread->unix_tid, param.sched_priority );
- + break;
- + case THREAD_PRIORITY_HIGHEST:
- + param.sched_priority = base_rt_priority;
- + policy = SCHED_RR;
- + fprintf( stderr, "Thread %i at THREAD_PRIORITY_HIGHEST set to SCHED_RR - priority %i\n", thread->unix_tid, param.sched_priority );
- + break;
- + case THREAD_PRIORITY_ABOVE_NORMAL:
- + param.sched_priority = 0;
- + policy = 4;
- + fprintf( stderr, "Thread %i at THREAD_PRIORITY_ABOVE_NORMAL set to SCHED_ISO - priority %i\n", thread->unix_tid, param.sched_priority );
- + break;
- + case THREAD_PRIORITY_NORMAL:
- + param.sched_priority = 0;
- + policy = SCHED_NORMAL;
- + fprintf( stderr, "Setting thread %i at level THREAD_PRIORITY_NORMAL to SCHED_NORMAL\n", thread->unix_tid );
- + break;
- + case THREAD_PRIORITY_BELOW_NORMAL:
- + param.sched_priority = 0;
- + policy = SCHED_BATCH;
- + fprintf( stderr, "Setting thread %i at level THREAD_PRIORITY_BELOW_NORMAL to SCHED_BATCH\n", thread->unix_tid );
- + break;
- + case THREAD_PRIORITY_LOWEST:
- + param.sched_priority = 0;
- + policy = SCHED_BATCH;
- + fprintf( stderr, "Setting thread %i at THREAD_PRIORITY_LOWEST level to SCHED_BATCH\n", thread->unix_tid );
- + break;
- + case THREAD_PRIORITY_IDLE:
- + param.sched_priority = 0;
- + policy = SCHED_IDLE;
- + fprintf( stderr, "Setting thread %i with level THREAD_PRIORITY_IDLE to SCHED_IDLE\n", thread->unix_tid );
- + break;
- + default:
- + fprintf( stderr, "Error setting scheduling priority level, unknown should never come here\n" );
- + return;
- + }
- + if (sched_setscheduler (thread->unix_tid, policy, ¶m) != 0) fprintf (stderr, "Error setting priorities\n");
- + thread->priority = priority;
- + return;
- +#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)
- - {
- - int max = THREAD_PRIORITY_HIGHEST;
- - int min = THREAD_PRIORITY_LOWEST;
- - if (thread->process->priority == PROCESS_PRIOCLASS_REALTIME)
- - {
- - max = THREAD_PRIORITY_REALTIME_HIGHEST;
- - min = THREAD_PRIORITY_REALTIME_LOWEST;
- - }
- - if ((req->priority >= min && req->priority <= max) ||
- - req->priority == THREAD_PRIORITY_IDLE ||
- - req->priority == THREAD_PRIORITY_TIME_CRITICAL)
- - thread->priority = req->priority;
- - else
- - set_error( STATUS_INVALID_PARAMETER );
- - }
- + set_thread_priority( thread, req->priority );
- if (req->mask & SET_THREAD_INFO_AFFINITY)
- {
- if ((req->affinity & thread->process->affinity) != req->affinity)
- --
- 1.7.3.2
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement