This week only. Pastebin PRO Accounts Christmas Special! Don't miss out!Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

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