scheduler.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. /*
  2. * Scheduler priority management
  3. *
  4. * Copyright (C) 2015 Joakim Hernberg
  5. * Copyright (C) 2015 Sebastian Lackner
  6. *
  7. * This library is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public
  9. * License as published by the Free Software Foundation; either
  10. * version 2.1 of the License, or (at your option) any later version.
  11. *
  12. * This library is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this library; if not, write to the Free Software
  19. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  20. */
  21. #include "config.h"
  22. #define _GNU_SOURCE /* for SCHED_BATCH, SCHED_IDLE */
  23. #include <assert.h>
  24. #include <stdio.h>
  25. #include <stdarg.h>
  26. #ifdef HAVE_SYS_RESOURCE_H
  27. # include <sys/resource.h>
  28. #endif
  29. #ifdef HAVE_SCHED_H
  30. # include <sched.h>
  31. #endif
  32. #ifndef SCHED_RESET_ON_FORK
  33. # define SCHED_RESET_ON_FORK 0x40000000
  34. #endif
  35. #ifndef SCHED_IDLE
  36. #define SCHED_IDLE 5
  37. #endif
  38. #include "ntstatus.h"
  39. #define WIN32_NO_STATUS
  40. #include "winternl.h"
  41. #include "thread.h"
  42. #if defined(__linux__) && defined(HAVE_SYS_RESOURCE_H) && defined(HAVE_SCHED_H)
  43. static int thread_base_priority = -1;
  44. /* gets the priority value from an environment variable */
  45. static int get_priority( const char *variable, int min, int max )
  46. {
  47. const char *env;
  48. int val;
  49. env = getenv( variable );
  50. if (!env) return -1;
  51. val = atoi( env );
  52. if (val >= min && val <= max) return val;
  53. fprintf( stderr, "wineserver: %s should be between %d and %d\n", variable, min, max );
  54. return -1;
  55. }
  56. /* initializes the scheduler */
  57. void init_scheduler( void )
  58. {
  59. int min, max, priority;
  60. min = sched_get_priority_min( SCHED_FIFO );
  61. max = sched_get_priority_max( SCHED_FIFO );
  62. if (min == -1 || max == -1)
  63. return;
  64. /* change the wineserver priority */
  65. if ((priority = get_priority( "STAGING_RT_PRIORITY_SERVER", min, max )) != -1)
  66. {
  67. struct sched_param param;
  68. memset( &param, 0, sizeof(param) );
  69. param.sched_priority = priority;
  70. if (sched_setscheduler( 0, SCHED_FIFO | SCHED_RESET_ON_FORK, &param ) == -1 &&
  71. sched_setscheduler( 0, SCHED_FIFO, &param ) == -1)
  72. {
  73. fprintf( stderr, "wineserver: failed to change priority to SCHED_FIFO/%d\n",
  74. param.sched_priority );
  75. /* do not bother to check the rest */
  76. return;
  77. }
  78. if (debug_level) fprintf( stderr, "wineserver: changed priority to SCHED_FIFO/%d\n",
  79. param.sched_priority );
  80. }
  81. /* determine base priority which will be used for all threads */
  82. if ((priority = get_priority( "STAGING_RT_PRIORITY_BASE", min, max - 4 )) != -1)
  83. {
  84. thread_base_priority = priority;
  85. if (debug_level) fprintf( stderr, "wineserver: initialized thread base priority to %d\n",
  86. thread_base_priority );
  87. }
  88. }
  89. /* sets the scheduler priority of a windows thread */
  90. void set_scheduler_priority( struct thread *thread )
  91. {
  92. struct sched_param param;
  93. int policy;
  94. if (thread_base_priority == -1) return;
  95. if (thread->unix_tid == -1) return;
  96. memset( &param, 0, sizeof(param) );
  97. if (thread->priority >= THREAD_PRIORITY_TIME_CRITICAL)
  98. {
  99. policy = SCHED_FIFO;
  100. param.sched_priority = thread_base_priority + 4;
  101. }
  102. else if (thread->priority >= THREAD_PRIORITY_HIGHEST)
  103. {
  104. policy = SCHED_FIFO;
  105. param.sched_priority = thread_base_priority + 2;
  106. }
  107. else if (thread->priority >= THREAD_PRIORITY_ABOVE_NORMAL)
  108. {
  109. policy = SCHED_FIFO;
  110. param.sched_priority = thread_base_priority;
  111. }
  112. else if (thread->priority >= THREAD_PRIORITY_NORMAL)
  113. {
  114. policy = SCHED_OTHER;
  115. }
  116. else if (thread->priority >= THREAD_PRIORITY_LOWEST)
  117. {
  118. policy = SCHED_BATCH;
  119. }
  120. else
  121. {
  122. policy = SCHED_IDLE;
  123. }
  124. if (sched_setscheduler(thread->unix_tid, policy | SCHED_RESET_ON_FORK, &param) == -1 &&
  125. sched_setscheduler(thread->unix_tid, policy, &param) == -1)
  126. {
  127. static int once;
  128. if (debug_level || !once++)
  129. fprintf( stderr, "%04x: failed to change priority to %d/%d\n",
  130. thread->id, policy, param.sched_priority );
  131. return;
  132. }
  133. if (debug_level) fprintf( stderr, "%04x: changed priority to %d/%d\n",
  134. thread->id, policy, param.sched_priority );
  135. }
  136. #else
  137. void init_scheduler( void )
  138. {
  139. }
  140. void set_scheduler_priority( struct thread *thread )
  141. {
  142. }
  143. #endif