2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * IPRT - Scheduling, Darwin.
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2006-2011 Oracle Corporation
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * available from http://www.virtualbox.org. This file is free software;
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * you can redistribute it and/or modify it under the terms of the GNU
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * General Public License (GPL) as published by the Free Software
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * The contents of this file may alternatively be used under the terms
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * of the Common Development and Distribution License Version 1.0
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * VirtualBox OSE distribution, in which case the provisions of the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * CDDL are applicable instead of those of the GPL.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * You may elect to license modified versions of this file under the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * terms and conditions of either the GPL or the CDDL or both.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync/*******************************************************************************
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync* Header Files *
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync*******************************************************************************/
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync/*******************************************************************************
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync* Structures and Typedefs *
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync*******************************************************************************/
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Configuration of one priority.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsynctypedef struct
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync /** The priority. */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync /** The name of this priority. */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync /** Array scheduler attributes corresponding to each of the thread types. */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync /** For sanity include the array index. */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync /** The desired mach base_priority value. */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync /** The suggested priority value. (Same as iBasePriority seems to do the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * trick.) */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync/*******************************************************************************
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync* Global Variables *
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync*******************************************************************************/
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Array of static priority configurations.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * ASSUMES that pthread_setschedparam takes a sched_priority argument in the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * range 0..127, which is translated into mach base_priority 0..63 and mach
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * importance -31..32 (among other things). We also ASSUMES SCHED_OTHER.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * The base_priority range can be checked with tstDarwinSched, we're assuming it's
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * 0..63 for user processes.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Further we observe that fseventsd and mds both run at (mach) priority 50,
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * while Finder runs at 47. At priority 63 we find the dynamic pager, the login
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * window, UserEventAgent, SystemUIServer and coreaudiod. We do not wish to upset the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * dynamic pager, UI or audio, but we wish for I/O to not be bothered by spotlight
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync { RTTHREADTYPE_EMULATION, 31, 31 }, /* the default priority */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * The dynamic default priority configuration.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * This can be recalulated at runtime depending on what the
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * system allow us to do. Presently we don't do this as it seems
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Darwin generally lets us do whatever we want.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * @remarks this is the same as "Normal" above.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync { RTTHREADTYPE_EMULATION, 31, 31 }, /* the default priority */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync/** Pointer to the current priority configuration. */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsyncstatic const PROCPRIORITY *g_pProcessPriority = &g_aDefaultPriority;
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Get's the priority information for the current thread.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * @returns The base priority
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync /* the base_priority. */
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync mach_msg_type_number_t Count = POLICY_TIMESHARE_INFO_COUNT;
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync krc = thread_info(mach_thread_self(), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&TSInfo, &Count);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsyncDECLHIDDEN(int) rtSchedNativeCalcDefaultPriority(RTTHREADTYPE enmType)
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Get the current priority.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync int iBasePriority = rtSchedDarwinGetBasePriority();
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * If it doesn't match the default, select the closest one from the table.
b40a63b20b0dbb6f0c1834673718d41eb1622127vboxsync int offBest = RT_ABS(g_pProcessPriority->aTypes[enmType].iBasePriority - iBasePriority);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
b40a63b20b0dbb6f0c1834673718d41eb1622127vboxsync int off = RT_ABS(g_aPriorities[i].aTypes[enmType].iBasePriority - iBasePriority);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsyncDECLHIDDEN(int) rtProcNativeSetPriority(RTPROCPRIORITY enmPriority)
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync Assert(enmPriority > RTPROCPRIORITY_INVALID && enmPriority < RTPROCPRIORITY_LAST);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * No checks necessary, we assume we can set any priority in the user process range.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync const PROCPRIORITY *pProcessPriority = &g_aDefaultPriority;
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
c7ff622115966b69b482bd2896662e40d823b22fvboxsync ASMAtomicUoWritePtr(&g_pProcessPriority, pProcessPriority);
5eda82e218d35ae0691febd531e1bfc0324cc4a6vboxsyncDECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync AssertMsg(g_pProcessPriority && g_pProcessPriority->aTypes[enmType].enmType == enmType,
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync ("enmType=%d entry=%d\n", enmType, g_pProcessPriority->aTypes[enmType].enmType));
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Get the current policy and params first since there are
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * opaque members in the param structure and we don't wish to
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * change the policy.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync int err = pthread_getschedparam((pthread_t)pThread->Core.Key, &iSchedPolicy, &SchedParam);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync int const iDesiredBasePriority = g_pProcessPriority->aTypes[enmType].iBasePriority;
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync int iPriority = g_pProcessPriority->aTypes[enmType].iPriority;
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * First try with the given pthread priority number.
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * Then make adjustments in case we missed the desired base priority (interface
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync * changed or whatever - its using an obsolete mach api).
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync int iBasePriority = rtSchedDarwinGetBasePriority();
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync while (!err && iBasePriority < iDesiredBasePriority && i++ < 256)
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync while (!err && iBasePriority > iDesiredBasePriority && i++ < 256)
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
2f6717afeb9f1572535794e226d5cfc84ba13d00vboxsync AssertMsgRC(rc, ("rc=%Rrc err=%d iSchedPolicy=%d sched_priority=%d\n",