VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/win/sched-win.cpp

Last change on this file was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 15.5 KB
Line 
1/* $Id: sched-win.cpp 98103 2023-01-17 14:15:46Z vboxsync $ */
2/** @file
3 * IPRT - Scheduling, Win32.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37/** @def WIN32_SCHED_ENABLED
38 * Enables the priority scheme. */
39#define WIN32_SCHED_ENABLED
40
41
42/*********************************************************************************************************************************
43* Header Files *
44*********************************************************************************************************************************/
45#define LOG_GROUP RTLOGGROUP_THREAD
46#include <iprt/win/windows.h>
47
48#include <iprt/thread.h>
49#include <iprt/log.h>
50#include <iprt/assert.h>
51#include <iprt/errcore.h>
52#include "internal/sched.h"
53#include "internal/thread.h"
54
55
56/*********************************************************************************************************************************
57* Structures and Typedefs *
58*********************************************************************************************************************************/
59/**
60 * Configuration of one priority.
61 */
62typedef struct
63{
64 /** The priority. */
65 RTPROCPRIORITY enmPriority;
66 /** The name of this priority. */
67 const char *pszName;
68 /** The Win32 process priority class. If ANY_PROCESS_PRIORITY_CLASS the
69 * process priority class is left unchanged. */
70 DWORD dwProcessPriorityClass;
71 /** Array scheduler attributes corresponding to each of the thread types. */
72 struct
73 {
74 /** For sanity include the array index. */
75 RTTHREADTYPE enmType;
76 /** The Win32 thread priority. */
77 int iThreadPriority;
78 } aTypes[RTTHREADTYPE_END];
79} PROCPRIORITY;
80
81/** Matches any process priority class. */
82#define ANY_PROCESS_PRIORITY_CLASS (~0U)
83
84
85/*********************************************************************************************************************************
86* Global Variables *
87*********************************************************************************************************************************/
88/**
89 * Array of static priority configurations.
90 */
91static const PROCPRIORITY g_aPriorities[] =
92{
93 {
94 RTPROCPRIORITY_FLAT, "Flat", ANY_PROCESS_PRIORITY_CLASS,
95 {
96 { RTTHREADTYPE_INVALID, ~0 },
97 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_NORMAL },
98 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_NORMAL },
99 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_NORMAL },
100 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_NORMAL },
101 { RTTHREADTYPE_GUI, THREAD_PRIORITY_NORMAL },
102 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_NORMAL },
103 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_NORMAL },
104 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_NORMAL },
105 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_NORMAL },
106 { RTTHREADTYPE_IO, THREAD_PRIORITY_NORMAL },
107 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_NORMAL }
108 }
109 },
110 {
111 RTPROCPRIORITY_LOW, "Low - Below Normal", BELOW_NORMAL_PRIORITY_CLASS,
112 {
113 { RTTHREADTYPE_INVALID, ~0 },
114 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_LOWEST },
115 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_BELOW_NORMAL },
116 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_NORMAL },
117 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_NORMAL },
118 { RTTHREADTYPE_GUI, THREAD_PRIORITY_NORMAL },
119 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_NORMAL },
120 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_ABOVE_NORMAL },
121 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_ABOVE_NORMAL },
122 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_ABOVE_NORMAL },
123 { RTTHREADTYPE_IO, THREAD_PRIORITY_HIGHEST },
124 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_HIGHEST }
125 }
126 },
127 {
128 RTPROCPRIORITY_LOW, "Low", ANY_PROCESS_PRIORITY_CLASS,
129 {
130 { RTTHREADTYPE_INVALID, ~0 },
131 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_LOWEST },
132 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_LOWEST },
133 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_LOWEST },
134 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_BELOW_NORMAL },
135 { RTTHREADTYPE_GUI, THREAD_PRIORITY_BELOW_NORMAL },
136 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_BELOW_NORMAL },
137 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_NORMAL },
138 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_NORMAL },
139 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_NORMAL },
140 { RTTHREADTYPE_IO, THREAD_PRIORITY_NORMAL },
141 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_NORMAL }
142 }
143 },
144 {
145 RTPROCPRIORITY_NORMAL, "Normal - Normal", NORMAL_PRIORITY_CLASS,
146 {
147 { RTTHREADTYPE_INVALID, ~0 },
148 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_LOWEST },
149 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_LOWEST },
150 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_BELOW_NORMAL },
151 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_NORMAL },
152 { RTTHREADTYPE_GUI, THREAD_PRIORITY_NORMAL },
153 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_NORMAL },
154 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_ABOVE_NORMAL },
155 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_ABOVE_NORMAL },
156 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_ABOVE_NORMAL },
157 { RTTHREADTYPE_IO, THREAD_PRIORITY_ABOVE_NORMAL },
158 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_HIGHEST }
159 }
160 },
161 {
162 RTPROCPRIORITY_NORMAL, "Normal", ANY_PROCESS_PRIORITY_CLASS,
163 {
164 { RTTHREADTYPE_INVALID, ~0 },
165 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_LOWEST },
166 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_LOWEST },
167 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_BELOW_NORMAL },
168 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_NORMAL },
169 { RTTHREADTYPE_GUI, THREAD_PRIORITY_NORMAL },
170 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_NORMAL },
171 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_ABOVE_NORMAL },
172 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_ABOVE_NORMAL },
173 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_ABOVE_NORMAL },
174 { RTTHREADTYPE_IO, THREAD_PRIORITY_ABOVE_NORMAL },
175 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_HIGHEST }
176 }
177 },
178 {
179 RTPROCPRIORITY_HIGH, "High - High", HIGH_PRIORITY_CLASS,
180 {
181 { RTTHREADTYPE_INVALID, ~0 },
182 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_LOWEST },
183 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_LOWEST },
184 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_BELOW_NORMAL },
185 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_NORMAL },
186 { RTTHREADTYPE_GUI, THREAD_PRIORITY_NORMAL },
187 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_NORMAL },
188 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_ABOVE_NORMAL },
189 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_ABOVE_NORMAL },
190 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_ABOVE_NORMAL },
191 { RTTHREADTYPE_IO, THREAD_PRIORITY_HIGHEST },
192 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_HIGHEST }
193 }
194 },
195 {
196 RTPROCPRIORITY_HIGH, "High - Above Normal", ABOVE_NORMAL_PRIORITY_CLASS,
197 {
198 { RTTHREADTYPE_INVALID, ~0 },
199 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_LOWEST },
200 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_LOWEST },
201 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_BELOW_NORMAL },
202 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_NORMAL },
203 { RTTHREADTYPE_GUI, THREAD_PRIORITY_NORMAL },
204 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_NORMAL },
205 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_ABOVE_NORMAL },
206 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_ABOVE_NORMAL },
207 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_ABOVE_NORMAL },
208 { RTTHREADTYPE_IO, THREAD_PRIORITY_HIGHEST },
209 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_HIGHEST }
210 }
211 },
212 {
213 RTPROCPRIORITY_HIGH, "High", ANY_PROCESS_PRIORITY_CLASS,
214 {
215 { RTTHREADTYPE_INVALID, ~0 },
216 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_BELOW_NORMAL },
217 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_NORMAL },
218 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_NORMAL },
219 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_ABOVE_NORMAL },
220 { RTTHREADTYPE_GUI, THREAD_PRIORITY_ABOVE_NORMAL },
221 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_ABOVE_NORMAL },
222 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_ABOVE_NORMAL },
223 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_HIGHEST },
224 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_HIGHEST },
225 { RTTHREADTYPE_IO, THREAD_PRIORITY_HIGHEST },
226 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_HIGHEST }
227 }
228 }
229};
230
231/**
232 * The dynamic default priority configuration.
233 *
234 * This can be recalulated at runtime depending on what the
235 * system allow us to do. Presently we don't do this as it's
236 * generally not a bit issue on Win32 hosts.
237 */
238static PROCPRIORITY g_aDefaultPriority =
239{
240 RTPROCPRIORITY_LOW, "Default", ANY_PROCESS_PRIORITY_CLASS,
241 {
242 { RTTHREADTYPE_INVALID, ~0 },
243 { RTTHREADTYPE_INFREQUENT_POLLER, THREAD_PRIORITY_LOWEST },
244 { RTTHREADTYPE_MAIN_HEAVY_WORKER, THREAD_PRIORITY_BELOW_NORMAL },
245 { RTTHREADTYPE_EMULATION, THREAD_PRIORITY_NORMAL },
246 { RTTHREADTYPE_DEFAULT, THREAD_PRIORITY_NORMAL },
247 { RTTHREADTYPE_GUI, THREAD_PRIORITY_NORMAL },
248 { RTTHREADTYPE_MAIN_WORKER, THREAD_PRIORITY_NORMAL },
249 { RTTHREADTYPE_VRDP_IO, THREAD_PRIORITY_NORMAL },
250 { RTTHREADTYPE_DEBUGGER, THREAD_PRIORITY_ABOVE_NORMAL },
251 { RTTHREADTYPE_MSG_PUMP, THREAD_PRIORITY_ABOVE_NORMAL },
252 { RTTHREADTYPE_IO, THREAD_PRIORITY_HIGHEST },
253 { RTTHREADTYPE_TIMER, THREAD_PRIORITY_HIGHEST }
254 }
255};
256
257
258/** Pointer to the current priority configuration. */
259static const PROCPRIORITY *g_pProcessPriority = &g_aDefaultPriority;
260
261
262/**
263 * Calculate the scheduling properties for all the threads in the default
264 * process priority, assuming the current thread have the type enmType.
265 *
266 * @returns iprt status code.
267 * @param enmType The thread type to be assumed for the current thread.
268 */
269DECLHIDDEN(int) rtSchedNativeCalcDefaultPriority(RTTHREADTYPE enmType)
270{
271 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END); RT_NOREF_PV(enmType);
272 return VINF_SUCCESS;
273}
274
275
276DECLHIDDEN(int) rtProcNativeSetPriority(RTPROCPRIORITY enmPriority)
277{
278 Assert(enmPriority > RTPROCPRIORITY_INVALID && enmPriority < RTPROCPRIORITY_LAST); RT_NOREF_PV(enmPriority);
279
280 if (enmPriority == RTPROCPRIORITY_DEFAULT)
281 {
282 g_pProcessPriority = &g_aDefaultPriority;
283 return VINF_SUCCESS;
284 }
285
286 for (size_t i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
287 if ( g_aPriorities[i].enmPriority == enmPriority
288 && g_aPriorities[i].dwProcessPriorityClass == ANY_PROCESS_PRIORITY_CLASS)
289 {
290 g_pProcessPriority = &g_aPriorities[i];
291 return VINF_SUCCESS;
292 }
293
294 AssertFailedReturn(VERR_INTERNAL_ERROR);
295}
296
297
298/**
299 * Gets the win32 thread handle.
300 *
301 * @returns Valid win32 handle for the specified thread.
302 * @param pThread The thread.
303 */
304DECLINLINE(HANDLE) rtThreadNativeGetHandle(PRTTHREADINT pThread)
305{
306 if ((uintptr_t)pThread->Core.Key == GetCurrentThreadId())
307 return GetCurrentThread();
308 return (HANDLE)pThread->hThread;
309}
310
311
312DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
313{
314 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
315 AssertMsg(g_pProcessPriority && g_pProcessPriority->aTypes[enmType].enmType == enmType,
316 ("enmType=%d entry=%d\n", enmType, g_pProcessPriority->aTypes[enmType].enmType));
317
318#ifdef WIN32_SCHED_ENABLED
319 HANDLE hThread = rtThreadNativeGetHandle(pThread);
320 if ( hThread == NULL /* No handle for alien threads. */
321 || SetThreadPriority(hThread, g_pProcessPriority->aTypes[enmType].iThreadPriority))
322 return VINF_SUCCESS;
323
324 DWORD dwLastError = GetLastError();
325 int rc = RTErrConvertFromWin32(dwLastError);
326 AssertMsgFailed(("SetThreadPriority(%p, %d) failed, dwLastError=%d rc=%Rrc\n",
327 rtThreadNativeGetHandle(pThread), g_pProcessPriority->aTypes[enmType].iThreadPriority, dwLastError, rc));
328 return rc;
329#else
330 return VINF_SUCCESS;
331#endif
332}
333
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use