wok annotate wine-rt/stuff/wine-rt-101107.patch @ rev 20932

updated fop (1.0 -> 2.3)
author Hans-G?nter Theisgen
date Sat Mar 02 14:33:42 2019 +0100 (2019-03-02)
parents
children
rev   line source
al@13542 1 From 1dceb627db51a239a63ed5276f7e8911be6751bc Mon Sep 17 00:00:00 2001
al@13542 2 From: Joakim B Hernberg <jhernberg@alchemy.lu>
al@13542 3 Date: Sun, 7 Nov 2010 19:10:49 +0100
al@13542 4 Subject: [PATCH] 3:rd wine-rt patch 101107
al@13542 5
al@13542 6 ---
al@13542 7 README.WINE-RT | 27 +++++++++++++++++
al@13542 8 server/main.c | 60 ++++++++++++++++++++++++++++++++++++++
al@13542 9 server/thread.c | 87 ++++++++++++++++++++++++++++++++++++++++++------------
al@13542 10 3 files changed, 154 insertions(+), 20 deletions(-)
al@13542 11 create mode 100644 README.WINE-RT
al@13542 12
al@13542 13 diff --git a/README.WINE-RT b/README.WINE-RT
al@13542 14 new file mode 100644
al@13542 15 index 0000000..3f3f2c1
al@13542 16 --- /dev/null
al@13542 17 +++ b/README.WINE-RT
al@13542 18 @@ -0,0 +1,27 @@
al@13542 19 +What is it?
al@13542 20 +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.
al@13542 21 +Windows' concept of priority classes is not implemented at all.
al@13542 22 +
al@13542 23 +Please note that threads running SCHED_FIFO might hang your entire system, so please exercise caution!
al@13542 24 +
al@13542 25 +How does it work?
al@13542 26 +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.
al@13542 27 +
al@13542 28 +How to use it?
al@13542 29 +The Wine-RT functionality is not enabled by default. Instead it is controlled by 2 environment variables "WINE_RT" and "WINE_SRV_RT".
al@13542 30 +
al@13542 31 +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.
al@13542 32 +
al@13542 33 +WINE_SRV_RT makes the wineserver main thread run SCHED_FIFO. Valid values range from 1 to your system's rtprio max value.
al@13542 34 +
al@13542 35 +We can set these variables in 2 simple ways.
al@13542 36 +First one is using a terminal with "exports", like this:
al@13542 37 +export WINE_RT=#
al@13542 38 +export WINE_SRV_RT=#
al@13542 39 +wine <app>
al@13542 40 +
al@13542 41 +or just prefix your application with 'env VARIABLE=value', like this:
al@13542 42 +env WINE_RT=# WINE_SRV_RT=# wine <app>
al@13542 43 +
al@13542 44 +A recommended starting point might be "env WINE_RT=15 WINE_SRV_RT=10 wine appname.exe".
al@13542 45 +
al@13542 46 diff --git a/server/main.c b/server/main.c
al@13542 47 index 2d841e8..a89d1e0 100644
al@13542 48 --- a/server/main.c
al@13542 49 +++ b/server/main.c
al@13542 50 @@ -27,10 +27,18 @@
al@13542 51 #include <stdio.h>
al@13542 52 #include <stdlib.h>
al@13542 53 #include <sys/time.h>
al@13542 54 +#include <sys/resource.h>
al@13542 55 +#include <sys/mman.h>
al@13542 56 #include <unistd.h>
al@13542 57 #ifdef HAVE_GETOPT_H
al@13542 58 # include <getopt.h>
al@13542 59 #endif
al@13542 60 +#ifdef HAVE_SCHED_H
al@13542 61 +#include <sched.h>
al@13542 62 +#ifndef SCHED_NORMAL
al@13542 63 +#define SCHED_NORMAL SCHED_OTHER
al@13542 64 +#endif
al@13542 65 +#endif
al@13542 66
al@13542 67 #include "object.h"
al@13542 68 #include "file.h"
al@13542 69 @@ -44,6 +52,9 @@ int foreground = 0;
al@13542 70 timeout_t master_socket_timeout = 3 * -TICKS_PER_SEC; /* master socket timeout, default is 3 seconds */
al@13542 71 const char *server_argv0;
al@13542 72
al@13542 73 +/* global variable used here and in thread.c to determine whether wine runs with rt threads and at what base value */
al@13542 74 +int base_rt_priority = -1;
al@13542 75 +
al@13542 76 /* parse-line args */
al@13542 77
al@13542 78 static void usage(void)
al@13542 79 @@ -125,6 +136,51 @@ static void sigterm_handler( int signum )
al@13542 80 exit(1); /* make sure atexit functions get called */
al@13542 81 }
al@13542 82
al@13542 83 +#ifdef HAVE_SCHED_H
al@13542 84 +void init_rt_scheduling( void )
al@13542 85 +{
al@13542 86 + struct sched_param param;
al@13542 87 + struct rlimit limit;
al@13542 88 + int priority_max, policy, wine_server_rt_priority;
al@13542 89 + char *enviroment, *endptr;
al@13542 90 +
al@13542 91 + getrlimit( RLIMIT_RTPRIO, &limit );
al@13542 92 + priority_max = limit.rlim_max;
al@13542 93 +
al@13542 94 + /* check for realtime mode and set the base priority level */
al@13542 95 +
al@13542 96 + if (!(enviroment = getenv( "WINE_RT" )))
al@13542 97 + return;
al@13542 98 + base_rt_priority = (int) strtol( enviroment, &endptr, 10 );
al@13542 99 + if (enviroment == endptr || base_rt_priority == 0 || base_rt_priority > priority_max - 10)
al@13542 100 + {
al@13542 101 + 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 );
al@13542 102 + base_rt_priority = -1;
al@13542 103 + return;
al@13542 104 + }
al@13542 105 + fprintf( stderr, "WINE realtime scheduling hack enabled, realtime base priority has been set to %i\n", base_rt_priority );
al@13542 106 +
al@13542 107 + /* determine scheduling policy for the main wineserver thread */
al@13542 108 +
al@13542 109 + if (!(enviroment = getenv( "WINE_SRV_RT" )))
al@13542 110 + {
al@13542 111 + fprintf( stderr, "wineserver running SCHED_NORMAL\n" );
al@13542 112 + return;
al@13542 113 + }
al@13542 114 + wine_server_rt_priority = (int) strtol( enviroment, &endptr, 10 );
al@13542 115 + if (enviroment == endptr || wine_server_rt_priority == 0 || wine_server_rt_priority > priority_max)
al@13542 116 + {
al@13542 117 + fprintf( stderr, "Unable to run the wineserver SCHED_FIFO, valid WINE_SRV_RT values range from 1 to %i\n", priority_max );
al@13542 118 + return;
al@13542 119 + }
al@13542 120 + fprintf( stderr, "wineserver running SCHED_FIFO at priority %i\n", wine_server_rt_priority );
al@13542 121 + policy = SCHED_FIFO;
al@13542 122 + param.sched_priority = wine_server_rt_priority;
al@13542 123 + if (sched_setscheduler ( 0, policy, &param) != 0)
al@13542 124 + fprintf (stderr, "Error scheduling wineserver as SCHED_FIFO\n");
al@13542 125 +}
al@13542 126 +#endif
al@13542 127 +
al@13542 128 int main( int argc, char *argv[] )
al@13542 129 {
al@13542 130 setvbuf( stderr, NULL, _IOLBF, 0 );
al@13542 131 @@ -138,6 +194,10 @@ int main( int argc, char *argv[] )
al@13542 132 signal( SIGTERM, sigterm_handler );
al@13542 133 signal( SIGABRT, sigterm_handler );
al@13542 134
al@13542 135 +#ifdef HAVE_SCHED_H
al@13542 136 + init_rt_scheduling();
al@13542 137 +#endif
al@13542 138 + mlockall(MCL_FUTURE);
al@13542 139 sock_init();
al@13542 140 open_master_socket();
al@13542 141
al@13542 142 diff --git a/server/thread.c b/server/thread.c
al@13542 143 index 05e4121..2d103b4 100644
al@13542 144 --- a/server/thread.c
al@13542 145 +++ b/server/thread.c
al@13542 146 @@ -32,11 +32,18 @@
al@13542 147 #include <sys/types.h>
al@13542 148 #include <unistd.h>
al@13542 149 #include <time.h>
al@13542 150 -#ifdef HAVE_POLL_H
al@13542 151 -#include <poll.h>
al@13542 152 -#endif
al@13542 153 #ifdef HAVE_SCHED_H
al@13542 154 #include <sched.h>
al@13542 155 +#ifndef SCHED_NORMAL
al@13542 156 +#define SCHED_NORMAL SCHED_OTHER
al@13542 157 +#endif
al@13542 158 +#ifndef SCHED_IDLE
al@13542 159 +#define SCHED_IDLE 5 /* missing from my glibc, taken from linux/sched.h */
al@13542 160 +#endif
al@13542 161 +#endif
al@13542 162 +
al@13542 163 +#ifdef HAVE_POLL_H
al@13542 164 +#include <poll.h>
al@13542 165 #endif
al@13542 166
al@13542 167 #include "ntstatus.h"
al@13542 168 @@ -164,6 +171,8 @@ static const struct fd_ops thread_fd_ops =
al@13542 169
al@13542 170 static struct list thread_list = LIST_INIT(thread_list);
al@13542 171
al@13542 172 +extern int base_rt_priority;
al@13542 173 +
al@13542 174 /* initialize the structure for a newly allocated thread */
al@13542 175 static inline void init_thread_structure( struct thread *thread )
al@13542 176 {
al@13542 177 @@ -432,29 +441,67 @@ int set_thread_affinity( struct thread *thread, affinity_t affinity )
al@13542 178 return ret;
al@13542 179 }
al@13542 180
al@13542 181 -#define THREAD_PRIORITY_REALTIME_HIGHEST 6
al@13542 182 -#define THREAD_PRIORITY_REALTIME_LOWEST -7
al@13542 183 +void set_thread_priority( struct thread *thread, int priority )
al@13542 184 +{
al@13542 185 +#ifdef HAVE_SCHED_H
al@13542 186 + struct sched_param param;
al@13542 187 + int policy;
al@13542 188 +
al@13542 189 + if (base_rt_priority == -1 || (thread->unix_tid == -1)) return;
al@13542 190 +
al@13542 191 + switch (priority)
al@13542 192 + {
al@13542 193 + case THREAD_PRIORITY_TIME_CRITICAL:
al@13542 194 + param.sched_priority = base_rt_priority + 10;
al@13542 195 + policy = SCHED_FIFO;
al@13542 196 + fprintf( stderr, "Thread %i at THREAD_PRIORITY_TIME_CRITICAL set to SCHED_FIFO - priority %i\n", thread->unix_tid, param.sched_priority );
al@13542 197 + break;
al@13542 198 + case THREAD_PRIORITY_HIGHEST:
al@13542 199 + param.sched_priority = base_rt_priority + 5;
al@13542 200 + policy = SCHED_FIFO;
al@13542 201 + fprintf( stderr, "Thread %i at THREAD_PRIORITY_HIGHEST set to SCHED_FIFO - priority %i\n", thread->unix_tid, param.sched_priority );
al@13542 202 + break;
al@13542 203 + case THREAD_PRIORITY_ABOVE_NORMAL:
al@13542 204 + param.sched_priority = base_rt_priority;
al@13542 205 + policy = SCHED_FIFO;
al@13542 206 + fprintf( stderr, "Thread %i at THREAD_PRIORITY_ABOVE_NORMAL set to SCHED_FIFO - priority %i\n", thread->unix_tid, param.sched_priority );
al@13542 207 + break;
al@13542 208 + case THREAD_PRIORITY_NORMAL:
al@13542 209 + param.sched_priority = 0;
al@13542 210 + policy = SCHED_NORMAL;
al@13542 211 + fprintf( stderr, "Setting thread %i at level THREAD_PRIORITY_NORMAL to SCHED_NORMAL\n", thread->unix_tid );
al@13542 212 + break;
al@13542 213 + case THREAD_PRIORITY_BELOW_NORMAL:
al@13542 214 + param.sched_priority = 0;
al@13542 215 + policy = SCHED_BATCH;
al@13542 216 + fprintf( stderr, "Setting thread %i at level THREAD_PRIORITY_BELOW_NORMAL to SCHED_BATCH\n", thread->unix_tid );
al@13542 217 + break;
al@13542 218 + case THREAD_PRIORITY_LOWEST:
al@13542 219 + param.sched_priority = 0;
al@13542 220 + policy = SCHED_BATCH;
al@13542 221 + fprintf( stderr, "Setting thread %i at THREAD_PRIORITY_LOWEST level to SCHED_BATCH\n", thread->unix_tid );
al@13542 222 + break;
al@13542 223 + case THREAD_PRIORITY_IDLE:
al@13542 224 + param.sched_priority = 0;
al@13542 225 + policy = SCHED_IDLE;
al@13542 226 + fprintf( stderr, "Setting thread %i with level THREAD_PRIORITY_IDLE to SCHED_IDLE\n", thread->unix_tid );
al@13542 227 + break;
al@13542 228 + default:
al@13542 229 + fprintf( stderr, "Error setting scheduling priority level, unknown should never come here\n" );
al@13542 230 + return;
al@13542 231 + }
al@13542 232 + if (sched_setscheduler (thread->unix_tid, policy, &param) != 0) fprintf (stderr, "Error setting priorities\n");
al@13542 233 + thread->priority = priority;
al@13542 234 + return;
al@13542 235 +#endif
al@13542 236 +}
al@13542 237
al@13542 238 /* set all information about a thread */
al@13542 239 static void set_thread_info( struct thread *thread,
al@13542 240 const struct set_thread_info_request *req )
al@13542 241 {
al@13542 242 if (req->mask & SET_THREAD_INFO_PRIORITY)
al@13542 243 - {
al@13542 244 - int max = THREAD_PRIORITY_HIGHEST;
al@13542 245 - int min = THREAD_PRIORITY_LOWEST;
al@13542 246 - if (thread->process->priority == PROCESS_PRIOCLASS_REALTIME)
al@13542 247 - {
al@13542 248 - max = THREAD_PRIORITY_REALTIME_HIGHEST;
al@13542 249 - min = THREAD_PRIORITY_REALTIME_LOWEST;
al@13542 250 - }
al@13542 251 - if ((req->priority >= min && req->priority <= max) ||
al@13542 252 - req->priority == THREAD_PRIORITY_IDLE ||
al@13542 253 - req->priority == THREAD_PRIORITY_TIME_CRITICAL)
al@13542 254 - thread->priority = req->priority;
al@13542 255 - else
al@13542 256 - set_error( STATUS_INVALID_PARAMETER );
al@13542 257 - }
al@13542 258 + set_thread_priority( thread, req->priority );
al@13542 259 if (req->mask & SET_THREAD_INFO_AFFINITY)
al@13542 260 {
al@13542 261 if ((req->affinity & thread->process->affinity) != req->affinity)
al@13542 262 --
al@13542 263 1.7.3.2
al@13542 264