/** * The process priority validator thread. * (We don't want to mess with the priority of the calling thread.) */ static void *rtSchedNativeValidatorThread(void *pvUser) { const PROCPRIORITY *pCfg = (const PROCPRIORITY *)pvUser; SAVEDPRIORITY SavedPriority; rtSchedNativeSave(&SavedPriority); /* * Try out the priorities from the top and down. */ int rc = VINF_SUCCESS; int i = RTTHREADTYPE_END; while (--i > RTTHREADTYPE_INVALID) { int iPriority = pCfg->paTypes[i].iPriority + pCfg->iDelta; if (setpriority(PRIO_PROCESS, 0, iPriority)) { rc = RTErrConvertFromErrno(errno); break; } } /* done */ rtSchedNativeRestore(&SavedPriority); return (void *)(intptr_t)rc; }
/** * The process priority validator thread. * (We don't want to mess with the priority of the calling thread.) */ static void *rtSchedNativeValidatorThread(void *pvUser) { PVALIDATORPRIORITYPAIR pPrioPair = (PVALIDATORPRIORITYPAIR)pvUser; SAVEDPRIORITY SavedPriority; rtSchedNativeSave(&SavedPriority); int rc = VINF_SUCCESS; /* * Set the priority to the current value for specified thread type, but * only if we have any threads of this type (caller checked - INT_MAX). */ if (pPrioPair->iCurrent != INT_MAX) if (setpriority(PRIO_PROCESS, 0, pPrioPair->iCurrent)) rc = RTErrConvertFromErrno(errno); /* * Try set the new priority. */ if (RT_SUCCESS(rc) && setpriority(PRIO_PROCESS, 0, pPrioPair->iNew)) rc = RTErrConvertFromErrno(errno); /* done */ rtSchedNativeRestore(&SavedPriority); return (void *)(intptr_t)rc; }
/** * The prober thread. * We don't want to mess with the priority of the calling thread. * * @remark This is pretty presumptive stuff, but if it works on Linux and * FreeBSD it does what I want. */ static void *rtSchedNativeProberThread(void *pvUser) { SAVEDPRIORITY SavedPriority; rtSchedNativeSave(&SavedPriority); /* * Let's first try and see what we get on a thread level. */ int iMax = sched_get_priority_max(SavedPriority.iPthreadPolicy); int iMin = sched_get_priority_min(SavedPriority.iPthreadPolicy); if (iMax - iMin >= 32) { pthread_t Self = pthread_self(); int i = iMin; while (i <= iMax) { struct sched_param SchedParam = SavedPriority.PthreadSchedParam; SchedParam.sched_priority = i; if (pthread_setschedparam(Self, SavedPriority.iPthreadPolicy, &SchedParam)) break; i++; } if (i == iMax) g_enmOsPrioSup = OSPRIOSUP_PROCESS_AND_THREAD_LEVEL; } /* * Ok, we didn't have the good stuff, so let's fall back on the unix stuff. */ if (g_enmOsPrioSup == OSPRIOSUP_UNDETERMINED) g_enmOsPrioSup = OSPRIOSUP_THREAD_LEVEL; /* * Check if we can get higher priority (typically only root can do this). * (Won't work right if our priority is -19 to start with, but what the heck.) * * We assume that the unix priority is -19 to 19. I know there are defines * for this, but I don't remember which and if I'm awake enough to make sense * of them from any SuS spec. */ int iStart = getpriority(PRIO_PROCESS, 0); int i = iStart; while (i-- > -19) { if (setpriority(PRIO_PROCESS, 0, i)) break; } if (getpriority(PRIO_PROCESS, 0) != iStart) g_fCanNice = true; else g_fCanNice = false; /* done */ rtSchedNativeRestore(&SavedPriority); return (void *)VINF_SUCCESS; }
/** * The prober thread. * We don't want to mess with the priority of the calling thread. * * @remark This is pretty presumptive stuff, but if it works on Linux and * FreeBSD it does what I want. */ static void *rtSchedNativeProberThread(void *pvUser) { NOREF(pvUser); SAVEDPRIORITY SavedPriority; rtSchedNativeSave(&SavedPriority); /* * Check if we can get higher priority (typically only root can do this). * (Won't work right if our priority is -19 to start with, but what the heck.) * * We assume that the priority range is -19 to 19. Should probably find the right * define for this. */ int iStart = getpriority(PRIO_PROCESS, 0); int i = iStart; while (i-- > -20) if (setpriority(PRIO_PROCESS, 0, i)) break; g_iMaxPriority = getpriority(PRIO_PROCESS, 0); g_fCanRaisePriority = g_iMaxPriority < iStart; g_fCanRestorePriority = setpriority(PRIO_PROCESS, 0, iStart) == 0; /* * Check if we temporarily lower the thread priority. * Again, we assume we're not at the extreme end of the priority scale. */ iStart = getpriority(PRIO_PROCESS, 0); i = iStart; while (i++ < 19) if (setpriority(PRIO_PROCESS, 0, i)) break; g_iMinPriority = getpriority(PRIO_PROCESS, 0); if ( setpriority(PRIO_PROCESS, 0, iStart) || getpriority(PRIO_PROCESS, 0) != iStart) g_fCanRestorePriority = false; if (g_iMinPriority == g_iMaxPriority) g_fCanRestorePriority = g_fCanRaisePriority = false; /* * Check what happens to child threads when the parent lowers the * priority when it's being created. */ iStart = getpriority(PRIO_PROCESS, 0); g_fScrewedUpMaxPriorityLimitInheritance = true; if ( g_fCanRestorePriority && !setpriority(PRIO_PROCESS, 0, g_iMinPriority) && iStart != g_iMinPriority) { if (rtSchedRunThread(rtSchedNativeSubProberThread, (void *)(intptr_t)iStart) == 0) g_fScrewedUpMaxPriorityLimitInheritance = false; } /* done */ rtSchedNativeRestore(&SavedPriority); return (void *)VINF_SUCCESS; }
/** * The validator thread. * We don't want to mess with the priority of the calling thread. * * @remark This is pretty presumptive stuff, but if it works on Linux and * FreeBSD it does what I want. */ static void *rtSchedNativeValidatorThread(void *pvUser) { const PROCPRIORITY *pCfg = (const PROCPRIORITY *)pvUser; SAVEDPRIORITY SavedPriority; rtSchedNativeSave(&SavedPriority); int rc = VINF_SUCCESS; switch (g_enmOsPrioSup) { /* * Try set the specified process priority and then try * out all the thread priorities which are used. */ case OSPRIOSUP_PROCESS_AND_THREAD_LEVEL: { if (!setpriority(PRIO_PROCESS, 0, pCfg->iNice)) { int iMin = sched_get_priority_min(SavedPriority.iPolicy); pthread_t Self = pthread_self(); for (int i = RTTHREADTYPE_INVALID + 1; i < RTTHREADTYPE_END; i++) { struct sched_param SchedParam = SavedPriority.PthreadSchedParam; SchedParam.sched_priority = pCfg->paTypes[i].iPriority + pCfg->iDelta + iMin; rc = pthread_setschedparam(Self, SavedPriority.iPthreadPolicy, &SchedParam); if (rc) { rc = RTErrConvertFromErrno(rc); break; } } } else rc = RTErrConvertFromErrno(errno); break; } /* * Try out the priorities from the top and down. */ case OSPRIOSUP_THREAD_LEVEL: { int i = RTTHREADTYPE_END; while (--i > RTTHREADTYPE_INVALID) { int iPriority = pCfg->paTypes[i].iPriority + pCfg->iDelta; if (setpriority(PRIO_PROCESS, 0, iPriority)) { rc = RTErrConvertFromErrno(errno); break; } } break; } default: AssertFailed(); break; } /* done */ rtSchedNativeRestore(&SavedPriority); return (void *)rc; }