VirtualBox

source: vbox/trunk/src/VBox/Runtime/r3/linux/sched-linux.cpp@ 48935

Last change on this file since 48935 was 48935, checked in by vboxsync, 11 years ago

Runtime: Whitespace and svn:keyword cleanups by scm.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 22.8 KB
Line 
1/* $Id: sched-linux.cpp 48935 2013-10-07 21:19:37Z vboxsync $ */
2/** @file
3 * IPRT - Scheduling, POSIX.
4 */
5
6/*
7 * Copyright (C) 2006-2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*
28 * !WARNING!
29 *
30 * When talking about lowering and raising priority, we do *NOT* refer to
31 * the common direction priority values takes on unix systems (lower means
32 * higher). So, when we raise the priority of a linux thread the nice
33 * value will decrease, and when we lower the priority the nice value
34 * will increase. Confusing, right?
35 *
36 * !WARNING!
37 */
38
39
40
41/** @def THREAD_LOGGING
42 * Be very careful with enabling this, it may cause deadlocks when combined
43 * with the 'thread' logging prefix.
44 */
45#ifdef DOXYGEN_RUNNING
46# define THREAD_LOGGING
47#endif
48
49
50/*******************************************************************************
51* Header Files *
52*******************************************************************************/
53#define LOG_GROUP RTLOGGROUP_THREAD
54#include <errno.h>
55#include <pthread.h>
56#include <sched.h>
57#include <unistd.h>
58#include <sys/resource.h>
59
60#include <iprt/thread.h>
61#include <iprt/process.h>
62#include <iprt/semaphore.h>
63#include <iprt/string.h>
64#include <iprt/assert.h>
65#include <iprt/log.h>
66#include <iprt/err.h>
67#include "internal/sched.h"
68#include "internal/thread.h"
69
70
71/*******************************************************************************
72* Structures and Typedefs *
73*******************************************************************************/
74
75/** Array scheduler attributes corresponding to each of the thread types.
76 * @internal */
77typedef struct PROCPRIORITYTYPE
78{
79 /** For sanity include the array index. */
80 RTTHREADTYPE enmType;
81 /** The thread priority or nice delta - depends on which priority type. */
82 int iPriority;
83} PROCPRIORITYTYPE;
84
85
86/**
87 * Configuration of one priority.
88 * @internal
89 */
90typedef struct
91{
92 /** The priority. */
93 RTPROCPRIORITY enmPriority;
94 /** The name of this priority. */
95 const char *pszName;
96 /** The process nice value. */
97 int iNice;
98 /** The delta applied to the iPriority value. */
99 int iDelta;
100 /** Array scheduler attributes corresponding to each of the thread types. */
101 const PROCPRIORITYTYPE *paTypes;
102} PROCPRIORITY;
103
104
105/**
106 * Saved priority settings
107 * @internal
108 */
109typedef struct
110{
111 /** Process priority. */
112 int iPriority;
113 /** Process level. */
114 struct sched_param SchedParam;
115 /** Process level. */
116 int iPolicy;
117 /** pthread level. */
118 struct sched_param PthreadSchedParam;
119 /** pthread level. */
120 int iPthreadPolicy;
121} SAVEDPRIORITY, *PSAVEDPRIORITY;
122
123
124/*******************************************************************************
125* Global Variables *
126*******************************************************************************/
127/**
128 * Deltas for a process in which we are not restricted
129 * to only be lowering the priority.
130 */
131static const PROCPRIORITYTYPE g_aTypesLinuxFree[RTTHREADTYPE_END] =
132{
133 { RTTHREADTYPE_INVALID, -999999999 },
134 { RTTHREADTYPE_INFREQUENT_POLLER, +3 },
135 { RTTHREADTYPE_MAIN_HEAVY_WORKER, +2 },
136 { RTTHREADTYPE_EMULATION, +1 },
137 { RTTHREADTYPE_DEFAULT, 0 },
138 { RTTHREADTYPE_GUI, 0 },
139 { RTTHREADTYPE_MAIN_WORKER, 0 },
140 { RTTHREADTYPE_VRDP_IO, -1 },
141 { RTTHREADTYPE_DEBUGGER, -1 },
142 { RTTHREADTYPE_MSG_PUMP, -2 },
143 { RTTHREADTYPE_IO, -3 },
144 { RTTHREADTYPE_TIMER, -4 }
145};
146
147/**
148 * Deltas for a process in which we are restricted and can only lower the priority.
149 */
150static const PROCPRIORITYTYPE g_aTypesLinuxRestricted[RTTHREADTYPE_END] =
151{
152 { RTTHREADTYPE_INVALID, -999999999 },
153 { RTTHREADTYPE_INFREQUENT_POLLER, +3 },
154 { RTTHREADTYPE_MAIN_HEAVY_WORKER, +2 },
155 { RTTHREADTYPE_EMULATION, +1 },
156 { RTTHREADTYPE_DEFAULT, 0 },
157 { RTTHREADTYPE_GUI, 0 },
158 { RTTHREADTYPE_MAIN_WORKER, 0 },
159 { RTTHREADTYPE_VRDP_IO, 0 },
160 { RTTHREADTYPE_DEBUGGER, 0 },
161 { RTTHREADTYPE_MSG_PUMP, 0 },
162 { RTTHREADTYPE_IO, 0 },
163 { RTTHREADTYPE_TIMER, 0 }
164};
165
166/**
167 * All threads have the same priority.
168 *
169 * This is typically chosen when we find that we can't raise the priority
170 * to the process default of a thread created by a low priority thread.
171 */
172static const PROCPRIORITYTYPE g_aTypesLinuxFlat[RTTHREADTYPE_END] =
173{
174 { RTTHREADTYPE_INVALID, -999999999 },
175 { RTTHREADTYPE_INFREQUENT_POLLER, 0 },
176 { RTTHREADTYPE_MAIN_HEAVY_WORKER, 0 },
177 { RTTHREADTYPE_EMULATION, 0 },
178 { RTTHREADTYPE_DEFAULT, 0 },
179 { RTTHREADTYPE_GUI, 0 },
180 { RTTHREADTYPE_MAIN_WORKER, 0 },
181 { RTTHREADTYPE_VRDP_IO, 0 },
182 { RTTHREADTYPE_DEBUGGER, 0 },
183 { RTTHREADTYPE_MSG_PUMP, 0 },
184 { RTTHREADTYPE_IO, 0 },
185 { RTTHREADTYPE_TIMER, 0 }
186};
187
188/**
189 * Process and thread level priority, full access at thread level.
190 */
191static const PROCPRIORITY g_aUnixConfigs[] =
192{
193 { RTPROCPRIORITY_FLAT, "Flat", 0, 0, g_aTypesLinuxFlat },
194 { RTPROCPRIORITY_LOW, "Low", 9, 9, g_aTypesLinuxFree },
195 { RTPROCPRIORITY_LOW, "Low", 9, 9, g_aTypesLinuxFlat },
196 { RTPROCPRIORITY_LOW, "Low", 15, 15, g_aTypesLinuxFree },
197 { RTPROCPRIORITY_LOW, "Low", 15, 15, g_aTypesLinuxFlat },
198 { RTPROCPRIORITY_LOW, "Low", 17, 17, g_aTypesLinuxFree },
199 { RTPROCPRIORITY_LOW, "Low", 17, 17, g_aTypesLinuxFlat },
200 { RTPROCPRIORITY_LOW, "Low", 19, 19, g_aTypesLinuxFlat },
201 { RTPROCPRIORITY_LOW, "Low", 9, 9, g_aTypesLinuxRestricted },
202 { RTPROCPRIORITY_LOW, "Low", 15, 15, g_aTypesLinuxRestricted },
203 { RTPROCPRIORITY_LOW, "Low", 17, 17, g_aTypesLinuxRestricted },
204 { RTPROCPRIORITY_NORMAL, "Normal", 0, 0, g_aTypesLinuxFree },
205 { RTPROCPRIORITY_NORMAL, "Normal", 0, 0, g_aTypesLinuxRestricted },
206 { RTPROCPRIORITY_NORMAL, "Normal", 0, 0, g_aTypesLinuxFlat },
207 { RTPROCPRIORITY_HIGH, "High", -9, -9, g_aTypesLinuxFree },
208 { RTPROCPRIORITY_HIGH, "High", -7, -7, g_aTypesLinuxFree },
209 { RTPROCPRIORITY_HIGH, "High", -5, -5, g_aTypesLinuxFree },
210 { RTPROCPRIORITY_HIGH, "High", -3, -3, g_aTypesLinuxFree },
211 { RTPROCPRIORITY_HIGH, "High", -1, -1, g_aTypesLinuxFree },
212 { RTPROCPRIORITY_HIGH, "High", -9, -9, g_aTypesLinuxRestricted },
213 { RTPROCPRIORITY_HIGH, "High", -7, -7, g_aTypesLinuxRestricted },
214 { RTPROCPRIORITY_HIGH, "High", -5, -5, g_aTypesLinuxRestricted },
215 { RTPROCPRIORITY_HIGH, "High", -3, -3, g_aTypesLinuxRestricted },
216 { RTPROCPRIORITY_HIGH, "High", -1, -1, g_aTypesLinuxRestricted },
217 { RTPROCPRIORITY_HIGH, "High", -9, -9, g_aTypesLinuxFlat },
218 { RTPROCPRIORITY_HIGH, "High", -7, -7, g_aTypesLinuxFlat },
219 { RTPROCPRIORITY_HIGH, "High", -5, -5, g_aTypesLinuxFlat },
220 { RTPROCPRIORITY_HIGH, "High", -3, -3, g_aTypesLinuxFlat },
221 { RTPROCPRIORITY_HIGH, "High", -1, -1, g_aTypesLinuxFlat }
222};
223
224/**
225 * The dynamic default priority configuration.
226 *
227 * This will be recalulated at runtime depending on what the
228 * system allow us to do and what the current priority is.
229 */
230static PROCPRIORITY g_aDefaultPriority =
231{
232 RTPROCPRIORITY_LOW, "Default", 0, 0, g_aTypesLinuxRestricted
233};
234
235/** Pointer to the current priority configuration. */
236static const PROCPRIORITY *g_pProcessPriority = &g_aDefaultPriority;
237
238/** Set if we can raise the priority of a thread beyond the default.
239 *
240 * It might mean we have the CAP_SYS_NICE capability or that the
241 * process's RLIMIT_NICE is higher than the priority of the thread
242 * calculating the defaults.
243 */
244static bool g_fCanRaisePriority = false;
245
246/** Set if we can restore the priority after having temporarily lowered or raised it. */
247static bool g_fCanRestorePriority = false;
248
249/** Set if we can NOT raise the priority to the process default in a thread
250 * created by a thread running below the process default.
251 */
252static bool g_fScrewedUpMaxPriorityLimitInheritance = true;
253
254/** The highest priority we can set. */
255static int g_iMaxPriority = 0;
256
257/** The lower priority we can set. */
258static int g_iMinPriority = 19;
259
260/** Set when we've successfully determined the capabilities of the process and kernel. */
261static bool g_fInitialized = false;
262
263
264
265/*******************************************************************************
266* Internal Functions *
267*******************************************************************************/
268
269
270/**
271 * Saves all the scheduling attributes we can think of.
272 */
273static void rtSchedNativeSave(PSAVEDPRIORITY pSave)
274{
275 memset(pSave, 0xff, sizeof(*pSave));
276
277 errno = 0;
278 pSave->iPriority = getpriority(PRIO_PROCESS, 0 /* current process */);
279 Assert(errno == 0);
280
281 errno = 0;
282 sched_getparam(0 /* current process */, &pSave->SchedParam);
283 Assert(errno == 0);
284
285 errno = 0;
286 pSave->iPolicy = sched_getscheduler(0 /* current process */);
287 Assert(errno == 0);
288
289 int rc = pthread_getschedparam(pthread_self(), &pSave->iPthreadPolicy, &pSave->PthreadSchedParam);
290 Assert(rc == 0); NOREF(rc);
291}
292
293
294/**
295 * Restores scheduling attributes.
296 * Most of this won't work right, but anyway...
297 */
298static void rtSchedNativeRestore(PSAVEDPRIORITY pSave)
299{
300 setpriority(PRIO_PROCESS, 0, pSave->iPriority);
301 sched_setscheduler(0, pSave->iPolicy, &pSave->SchedParam);
302 sched_setparam(0, &pSave->SchedParam);
303 pthread_setschedparam(pthread_self(), pSave->iPthreadPolicy, &pSave->PthreadSchedParam);
304}
305
306
307/**
308 * Starts a worker thread and wait for it to complete.
309 * We cannot use RTThreadCreate since we're already owner of the RW lock.
310 */
311static int rtSchedRunThread(void *(*pfnThread)(void *pvArg), void *pvArg)
312{
313 /*
314 * Setup thread attributes.
315 */
316 pthread_attr_t ThreadAttr;
317 int rc = pthread_attr_init(&ThreadAttr);
318 if (!rc)
319 {
320 rc = pthread_attr_setdetachstate(&ThreadAttr, PTHREAD_CREATE_JOINABLE);
321 if (!rc)
322 {
323 rc = pthread_attr_setstacksize(&ThreadAttr, 128*1024);
324 if (!rc)
325 {
326 /*
327 * Create the thread.
328 */
329 pthread_t Thread;
330 rc = pthread_create(&Thread, &ThreadAttr, pfnThread, pvArg);
331 if (!rc)
332 {
333 /*
334 * Wait for the thread to finish.
335 */
336 void *pvRet = (void *)-1;
337 do
338 {
339 rc = pthread_join(Thread, &pvRet);
340 } while (errno == EINTR);
341 if (rc)
342 return RTErrConvertFromErrno(rc);
343 return (int)(uintptr_t)pvRet;
344 }
345 }
346 }
347 pthread_attr_destroy(&ThreadAttr);
348 }
349 return RTErrConvertFromErrno(rc);
350}
351
352
353static void rtSchedDumpPriority(void)
354{
355#ifdef THREAD_LOGGING
356 Log(("Priority: g_fCanRaisePriority=%RTbool g_fCanRestorePriority=%RTbool g_fScrewedUpMaxPriorityLimitInheritance=%RTbool\n",
357 g_fCanRaisePriority, g_fCanRestorePriority, g_fScrewedUpMaxPriorityLimitInheritance));
358 Log(("Priority: g_iMaxPriority=%d g_iMinPriority=%d\n", g_iMaxPriority, g_iMinPriority));
359 Log(("Priority: enmPriority=%d \"%s\" iNice=%d iDelta=%d\n",
360 g_pProcessPriority->enmPriority,
361 g_pProcessPriority->pszName,
362 g_pProcessPriority->iNice,
363 g_pProcessPriority->iDelta));
364 Log(("Priority: %2d INFREQUENT_POLLER = %d\n", RTTHREADTYPE_INFREQUENT_POLLER, g_pProcessPriority->paTypes[RTTHREADTYPE_INFREQUENT_POLLER].iPriority));
365 Log(("Priority: %2d MAIN_HEAVY_WORKER = %d\n", RTTHREADTYPE_MAIN_HEAVY_WORKER, g_pProcessPriority->paTypes[RTTHREADTYPE_MAIN_HEAVY_WORKER].iPriority));
366 Log(("Priority: %2d EMULATION = %d\n", RTTHREADTYPE_EMULATION , g_pProcessPriority->paTypes[RTTHREADTYPE_EMULATION ].iPriority));
367 Log(("Priority: %2d DEFAULT = %d\n", RTTHREADTYPE_DEFAULT , g_pProcessPriority->paTypes[RTTHREADTYPE_DEFAULT ].iPriority));
368 Log(("Priority: %2d GUI = %d\n", RTTHREADTYPE_GUI , g_pProcessPriority->paTypes[RTTHREADTYPE_GUI ].iPriority));
369 Log(("Priority: %2d MAIN_WORKER = %d\n", RTTHREADTYPE_MAIN_WORKER , g_pProcessPriority->paTypes[RTTHREADTYPE_MAIN_WORKER ].iPriority));
370 Log(("Priority: %2d VRDP_IO = %d\n", RTTHREADTYPE_VRDP_IO , g_pProcessPriority->paTypes[RTTHREADTYPE_VRDP_IO ].iPriority));
371 Log(("Priority: %2d DEBUGGER = %d\n", RTTHREADTYPE_DEBUGGER , g_pProcessPriority->paTypes[RTTHREADTYPE_DEBUGGER ].iPriority));
372 Log(("Priority: %2d MSG_PUMP = %d\n", RTTHREADTYPE_MSG_PUMP , g_pProcessPriority->paTypes[RTTHREADTYPE_MSG_PUMP ].iPriority));
373 Log(("Priority: %2d IO = %d\n", RTTHREADTYPE_IO , g_pProcessPriority->paTypes[RTTHREADTYPE_IO ].iPriority));
374 Log(("Priority: %2d TIMER = %d\n", RTTHREADTYPE_TIMER , g_pProcessPriority->paTypes[RTTHREADTYPE_TIMER ].iPriority));
375#endif
376}
377
378
379/**
380 * This just checks if it can raise the priority after having been
381 * created by a thread with a low priority.
382 *
383 * @returns zero on success, non-zero on failure.
384 * @param pvUser The priority of the parent before it was lowered (cast to int).
385 */
386static void *rtSchedNativeSubProberThread(void *pvUser)
387{
388 int iPriority = getpriority(PRIO_PROCESS, 0);
389 Assert(iPriority == g_iMinPriority);
390
391 if (setpriority(PRIO_PROCESS, 0, iPriority + 1))
392 return (void *)-1;
393 if (setpriority(PRIO_PROCESS, 0, (int)(intptr_t)pvUser))
394 return (void *)-1;
395 return (void *)0;
396}
397
398
399/**
400 * The prober thread.
401 * We don't want to mess with the priority of the calling thread.
402 *
403 * @remark This is pretty presumptive stuff, but if it works on Linux and
404 * FreeBSD it does what I want.
405 */
406static void *rtSchedNativeProberThread(void *pvUser)
407{
408 NOREF(pvUser);
409 SAVEDPRIORITY SavedPriority;
410 rtSchedNativeSave(&SavedPriority);
411
412 /*
413 * Check if we can get higher priority (typically only root can do this).
414 * (Won't work right if our priority is -19 to start with, but what the heck.)
415 *
416 * We assume that the priority range is -19 to 19. Should probably find the right
417 * define for this.
418 */
419 int iStart = getpriority(PRIO_PROCESS, 0);
420 int i = iStart;
421 while (i-- > -20)
422 if (setpriority(PRIO_PROCESS, 0, i))
423 break;
424 g_iMaxPriority = getpriority(PRIO_PROCESS, 0);
425 g_fCanRaisePriority = g_iMaxPriority < iStart;
426 g_fCanRestorePriority = setpriority(PRIO_PROCESS, 0, iStart) == 0;
427
428 /*
429 * Check if we temporarily lower the thread priority.
430 * Again, we assume we're not at the extreme end of the priority scale.
431 */
432 iStart = getpriority(PRIO_PROCESS, 0);
433 i = iStart;
434 while (i++ < 19)
435 if (setpriority(PRIO_PROCESS, 0, i))
436 break;
437 g_iMinPriority = getpriority(PRIO_PROCESS, 0);
438 if ( setpriority(PRIO_PROCESS, 0, iStart)
439 || getpriority(PRIO_PROCESS, 0) != iStart)
440 g_fCanRestorePriority = false;
441 if (g_iMinPriority == g_iMaxPriority)
442 g_fCanRestorePriority = g_fCanRaisePriority = false;
443
444 /*
445 * Check what happens to child threads when the parent lowers the
446 * priority when it's being created.
447 */
448 iStart = getpriority(PRIO_PROCESS, 0);
449 g_fScrewedUpMaxPriorityLimitInheritance = true;
450 if ( g_fCanRestorePriority
451 && !setpriority(PRIO_PROCESS, 0, g_iMinPriority)
452 && iStart != g_iMinPriority)
453 {
454 if (rtSchedRunThread(rtSchedNativeSubProberThread, (void *)(intptr_t)iStart) == 0)
455 g_fScrewedUpMaxPriorityLimitInheritance = false;
456 }
457
458 /* done */
459 rtSchedNativeRestore(&SavedPriority);
460 return (void *)VINF_SUCCESS;
461}
462
463
464/**
465 * Calculate the scheduling properties for all the threads in the default
466 * process priority, assuming the current thread have the type enmType.
467 *
468 * @returns iprt status code.
469 * @param enmType The thread type to be assumed for the current thread.
470 */
471DECLHIDDEN(int) rtSchedNativeCalcDefaultPriority(RTTHREADTYPE enmType)
472{
473 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
474
475 /*
476 * First figure out what's we're allowed to do in this process.
477 */
478 if (!g_fInitialized)
479 {
480 int iPriority = getpriority(PRIO_PROCESS, 0);
481#ifdef RLIMIT_RTPRIO
482 /** @todo */
483#endif
484 int rc = rtSchedRunThread(rtSchedNativeProberThread, NULL);
485 if (RT_FAILURE(rc))
486 return rc;
487 Assert(getpriority(PRIO_PROCESS, 0) == iPriority); NOREF(iPriority);
488 g_fInitialized = true;
489 }
490
491 /*
492 * Select the right priority type table and update the default
493 * process priority structure.
494 */
495 if (g_fCanRaisePriority && g_fCanRestorePriority && !g_fScrewedUpMaxPriorityLimitInheritance)
496 g_aDefaultPriority.paTypes = &g_aTypesLinuxFree[0];
497 else if (!g_fCanRaisePriority && g_fCanRestorePriority && !g_fScrewedUpMaxPriorityLimitInheritance)
498 g_aDefaultPriority.paTypes = &g_aTypesLinuxRestricted[0];
499 else
500 g_aDefaultPriority.paTypes = &g_aTypesLinuxFlat[0];
501 Assert(enmType == g_aDefaultPriority.paTypes[enmType].enmType);
502
503 int iPriority = getpriority(PRIO_PROCESS, 0 /* current process */);
504 g_aDefaultPriority.iNice = iPriority - g_aDefaultPriority.paTypes[enmType].iPriority;
505 g_aDefaultPriority.iDelta = g_aDefaultPriority.iNice;
506
507 rtSchedDumpPriority();
508 return VINF_SUCCESS;
509}
510
511
512/**
513 * The process priority validator thread.
514 * (We don't want to mess with the priority of the calling thread.)
515 */
516static void *rtSchedNativeValidatorThread(void *pvUser)
517{
518 const PROCPRIORITY *pCfg = (const PROCPRIORITY *)pvUser;
519 SAVEDPRIORITY SavedPriority;
520 rtSchedNativeSave(&SavedPriority);
521
522 /*
523 * Try out the priorities from the top and down.
524 */
525 int rc = VINF_SUCCESS;
526 int i = RTTHREADTYPE_END;
527 while (--i > RTTHREADTYPE_INVALID)
528 {
529 int iPriority = pCfg->paTypes[i].iPriority + pCfg->iDelta;
530 if (setpriority(PRIO_PROCESS, 0, iPriority))
531 {
532 rc = RTErrConvertFromErrno(errno);
533 break;
534 }
535 }
536
537 /* done */
538 rtSchedNativeRestore(&SavedPriority);
539 return (void *)(intptr_t)rc;
540}
541
542
543/**
544 * Validates and sets the process priority.
545 *
546 * This will check that all rtThreadNativeSetPriority() will success for all the
547 * thread types when applied to the current thread.
548 *
549 * @returns iprt status code.
550 * @param enmPriority The priority to validate and set.
551 */
552DECLHIDDEN(int) rtProcNativeSetPriority(RTPROCPRIORITY enmPriority)
553{
554 Assert(enmPriority > RTPROCPRIORITY_INVALID && enmPriority < RTPROCPRIORITY_LAST);
555
556 int rc = VINF_SUCCESS;
557 if (enmPriority == RTPROCPRIORITY_DEFAULT)
558 g_pProcessPriority = &g_aDefaultPriority;
559 else
560 {
561 /*
562 * Find a configuration which matches and can be applied.
563 */
564 rc = VERR_FILE_NOT_FOUND;
565 for (unsigned i = 0; i < RT_ELEMENTS(g_aUnixConfigs); i++)
566 {
567 if (g_aUnixConfigs[i].enmPriority == enmPriority)
568 {
569 int iPriority = getpriority(PRIO_PROCESS, 0);
570 int rc3 = rtSchedRunThread(rtSchedNativeValidatorThread, (void *)&g_aUnixConfigs[i]);
571 Assert(getpriority(PRIO_PROCESS, 0) == iPriority); NOREF(iPriority);
572 if (RT_SUCCESS(rc3))
573 {
574 g_pProcessPriority = &g_aUnixConfigs[i];
575 rc = VINF_SUCCESS;
576 break;
577 }
578 if (rc == VERR_FILE_NOT_FOUND)
579 rc = rc3;
580 }
581 }
582 }
583
584#ifdef THREAD_LOGGING
585 LogFlow(("rtProcNativeSetPriority: returns %Rrc enmPriority=%d\n", rc, enmPriority));
586 rtSchedDumpPriority();
587#endif
588 return rc;
589}
590
591
592/**
593 * Sets the priority of the thread according to the thread type
594 * and current process priority.
595 *
596 * The RTTHREADINT::enmType member has not yet been updated and will be updated by
597 * the caller on a successful return.
598 *
599 * @returns iprt status code.
600 * @param pThread The thread in question.
601 * @param enmType The thread type.
602 */
603DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
604{
605 /* sanity */
606 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
607 Assert(enmType == g_pProcessPriority->paTypes[enmType].enmType);
608 Assert((pthread_t)pThread->Core.Key == pthread_self());
609
610 /*
611 * Calculate the thread priority and apply it.
612 */
613 int rc = VINF_SUCCESS;
614 int iPriority = g_pProcessPriority->paTypes[enmType].iPriority + g_pProcessPriority->iDelta;
615 if (!setpriority(PRIO_PROCESS, 0, iPriority))
616 {
617 AssertMsg(iPriority == getpriority(PRIO_PROCESS, 0), ("iPriority=%d getpriority()=%d\n", iPriority, getpriority(PRIO_PROCESS, 0)));
618#ifdef THREAD_LOGGING
619 Log(("rtThreadNativeSetPriority: Thread=%p enmType=%d iPriority=%d pid=%d\n", pThread->Core.Key, enmType, iPriority, getpid()));
620#endif
621 }
622 else
623 {
624 rc = RTErrConvertFromErrno(errno);
625 AssertMsgFailed(("setpriority(,, %d) -> errno=%d rc=%Rrc\n", iPriority, errno, rc));
626 rc = VINF_SUCCESS; //non-fatal for now.
627 }
628
629 return rc;
630}
631
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette