VirtualBox

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

Last change on this file since 403 was 403, checked in by vboxsync, 18 years ago

Need RTThreadWait in ring-0 too when using the generic timers, so thread.cpp was ported to ring-0. Fixed a bug in RTTimerStart() (the generic code). (hope this doesn't break the other platforms...)

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