VirtualBox

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

Last change on this file since 27653 was 25642, checked in by vboxsync, 15 years ago

DOXYGEN -> DOXYGEN_RUNNING.

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