sched-darwin.cpp revision 2f6717afeb9f1572535794e226d5cfc84ba13d00
/* $Id$ */
/** @file
* IPRT - Scheduling, Darwin.
*/
/*
* Copyright (C) 2006-2009 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP RTLOGGROUP_THREAD
#include <mach/thread_act.h>
#include <mach/thread_policy.h>
#include <mach/thread_info.h>
#include <mach/host_info.h>
#include <mach/mach_init.h>
#include <mach/mach_host.h>
#include <sched.h>
#include <pthread.h>
#include <limits.h>
#include <errno.h>
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/**
* Configuration of one priority.
*/
typedef struct
{
/** The priority. */
/** The name of this priority. */
const char *pszName;
/** Array scheduler attributes corresponding to each of the thread types. */
struct
{
/** For sanity include the array index. */
/** The desired mach base_priority value. */
int iBasePriority;
/** The suggested priority value. (Same as iBasePriority seems to do the
* trick.) */
int iPriority;
} PROCPRIORITY;
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/**
* Array of static priority configurations.
*
* ASSUMES that pthread_setschedparam takes a sched_priority argument in the
* range 0..127, which is translated into mach base_priority 0..63 and mach
* importance -31..32 (among other things). We also ASSUMES SCHED_OTHER.
*
* The base_priority range can be checked with tstDarwinSched, we're assuming it's
* 0..63 for user processes.
*
* Further we observe that fseventsd and mds both run at (mach) priority 50,
* while Finder runs at 47. At priority 63 we find the dynamic pager, the login
* window, UserEventAgent, SystemUIServer and coreaudiod. We do not wish to upset the
* dynamic pager, UI or audio, but we wish for I/O to not be bothered by spotlight
*/
static const PROCPRIORITY g_aPriorities[] =
{
{
RTPROCPRIORITY_LOW, "Low",
{
}
},
{
RTPROCPRIORITY_NORMAL, "Normal",
{
}
},
{
RTPROCPRIORITY_HIGH, "High",
{
}
},
/* last */
{
RTPROCPRIORITY_FLAT, "Flat",
{
}
},
};
/**
* The dynamic default priority configuration.
*
* This can be recalulated at runtime depending on what the
* system allow us to do. Presently we don't do this as it seems
* Darwin generally lets us do whatever we want.
*
* @remarks this is the same as "Normal" above.
*/
static PROCPRIORITY g_aDefaultPriority =
{
RTPROCPRIORITY_DEFAULT, "Default",
{
}
};
/** Pointer to the current priority configuration. */
/**
* Get's the priority information for the current thread.
*
* @returns The base priority
*/
static int rtSchedDarwinGetBasePriority(void)
{
/* the base_priority. */
struct policy_timeshare_info TSInfo = {0,0,0,0,0};
return TSInfo.base_priority;
}
{
/*
* Get the current priority.
*/
/*
* If it doesn't match the default, select the closest one from the table.
*/
if (iCurDiff)
{
for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
{
if (iBasePriority < iCurDiff)
{
g_pProcessPriority = &g_aPriorities[i];
if (!iCurDiff)
break;
}
}
}
return VINF_SUCCESS;
}
{
/*
* No checks necessary, we assume we can set any priority in the user process range.
*/
for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
{
pProcessPriority = &g_aPriorities[i];
break;
}
return VINF_SUCCESS;
}
{
/*
* Get the current policy and params first since there are
* opaque members in the param structure and we don't wish to
* change the policy.
*/
int iSchedPolicy = SCHED_OTHER;
struct sched_param SchedParam = {0, {0,0,0,0} };
if (!err)
{
/*
* First try with the given pthread priority number.
* Then make adjustments in case we missed the desired base priority (interface
* changed or whatever - its using an obsolete mach api).
*/
if (!err)
{
int i = 0;
{
}
{
}
}
}
return rc;
}