VirtualBox

Changeset 15881 in vbox


Ignore:
Timestamp:
Jan 8, 2009 6:46:52 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
41492
Message:

IPRT: Implemented ring-3 priority scheme for darwin.

Location:
trunk/src/VBox/Runtime
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/Makefile.kmk

    r15843 r15881  
    452452        generic/RTUuidCreate-generic.cpp \
    453453        generic/mppresent-generic.cpp \
    454         generic/sched-generic.cpp \
    455454        generic/timer-generic.cpp \
    456455        generic/utf16locale-generic.cpp \
     
    460459        r3/darwin/mp-darwin.cpp \
    461460        r3/darwin/rtProcInitExePath-darwin.cpp \
     461        r3/darwin/sched-darwin.cpp \
    462462        r3/darwin/time-darwin.cpp \
    463463        r3/posix/RTSystemQueryOSInfo-posix.cpp \
  • trunk/src/VBox/Runtime/r3/darwin/sched-darwin.cpp

    r15866 r15881  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Scheduling, OS/2
     3 * IPRT - Scheduling, Darwin.
    44 */
    55
    66/*
    7  * Copyright (C) 2006-2007 Sun Microsystems, Inc.
     7 * Copyright (C) 2006-2009 Sun Microsystems, Inc.
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    2929 */
    3030
    31 /** @def OS2_SCHED_ENABLED
    32  * Enables the priority scheme. */
    33 #define OS2_SCHED_ENABLED
    34 
    3531
    3632/*******************************************************************************
     
    3834*******************************************************************************/
    3935#define LOG_GROUP RTLOGGROUP_THREAD
    40 #define INCL_BASE
    41 #define INCL_ERRORS
    42 #include <os2.h>
     36#include <mach/thread_act.h>
     37#include <mach/thread_policy.h>
     38#include <mach/thread_info.h>
     39#include <mach/host_info.h>
     40#include <mach/mach_init.h>
     41#include <mach/mach_host.h>
     42#include <sched.h>
     43#include <pthread.h>
     44#include <limits.h>
     45#include <errno.h>
    4346
    4447#include <iprt/thread.h>
     
    4649#include <iprt/assert.h>
    4750#include <iprt/err.h>
     51#include <iprt/asm.h>
     52#include <iprt/assert.h>
    4853#include "internal/sched.h"
    4954#include "internal/thread.h"
     
    6772        /** For sanity include the array index. */
    6873        RTTHREADTYPE    enmType;
    69         /** The OS/2 priority class. */
    70         ULONG           ulClass;
    71         /** The OS/2 priority delta. */
    72         ULONG           ulDelta;
     74        /** The desired mach base_priority value. */
     75        int             iBasePriority;
     76        /** The suggested priority value. (Same as iBasePriority seems to do the
     77         *  trick.) */
     78        int             iPriority;
    7379    } aTypes[RTTHREADTYPE_END];
    7480} PROCPRIORITY;
    75 
    76 /** Matches any process priority class. */
    77 #define ANY_PROCESS_PRIORITY_CLASS  (~0U)
    7881
    7982
     
    8386/**
    8487 * Array of static priority configurations.
     88 *
     89 * ASSUMES that pthread_setschedparam takes a sched_priority argument in the
     90 * range 0..127, which is translated into mach base_priority 0..63 and mach
     91 * importance -31..32 (among other things). We also ASSUMES SCHED_OTHER.
     92 *
     93 * The base_priority range can be checked with tstDarwinSched, we're assuming it's
     94 * 0..63 for user processes.
     95 *
     96 * Further we observe that fseventsd and mds both run at (mach) priority 50,
     97 * while Finder runs at 47. At priority 63 we find the dynamic pager, the login
     98 * window, UserEventAgent, SystemUIServer and coreaudiod. We do not wish to upset the
     99 * dynamic pager, UI or audio, but we wish for I/O to not be bothered by spotlight
     100 * (mds/fseventsd).
    85101 */
    86102static const PROCPRIORITY g_aPriorities[] =
    87103{
    88104    {
     105        RTPROCPRIORITY_LOW, "Low",
     106        {
     107            { RTTHREADTYPE_INVALID,                 INT_MIN, INT_MIN },
     108            { RTTHREADTYPE_INFREQUENT_POLLER,       20, 20 },
     109            { RTTHREADTYPE_MAIN_HEAVY_WORKER,       22, 22 },
     110            { RTTHREADTYPE_EMULATION,               24, 24 },
     111            { RTTHREADTYPE_DEFAULT,                 28, 28 },
     112            { RTTHREADTYPE_GUI,                     29, 29 },
     113            { RTTHREADTYPE_MAIN_WORKER,             30, 30 },
     114            { RTTHREADTYPE_VRDP_IO,                 31, 31 },
     115            { RTTHREADTYPE_DEBUGGER,                31, 31 },
     116            { RTTHREADTYPE_MSG_PUMP,                31, 31 },
     117            { RTTHREADTYPE_IO,                      31, 31 },
     118            { RTTHREADTYPE_TIMER,                   31, 31 }
     119        }
     120    },
     121    {
     122        RTPROCPRIORITY_NORMAL, "Normal",
     123        {
     124            { RTTHREADTYPE_INVALID,                 INT_MIN, INT_MIN },
     125            { RTTHREADTYPE_INFREQUENT_POLLER,       29, 29 },
     126            { RTTHREADTYPE_MAIN_HEAVY_WORKER,       30, 30 },
     127            { RTTHREADTYPE_EMULATION,               31, 31 }, /* the default priority */
     128            { RTTHREADTYPE_DEFAULT,                 32, 32 },
     129            { RTTHREADTYPE_GUI,                     32, 32 },
     130            { RTTHREADTYPE_MAIN_WORKER,             32, 32 },
     131            { RTTHREADTYPE_VRDP_IO,                 39, 39 },
     132            { RTTHREADTYPE_DEBUGGER,                42, 42 },
     133            { RTTHREADTYPE_MSG_PUMP,                47, 47 },
     134            { RTTHREADTYPE_IO,                      52, 52 },
     135            { RTTHREADTYPE_TIMER,                   55, 55 }
     136        }
     137    },
     138    {
     139        RTPROCPRIORITY_HIGH, "High",
     140        {
     141            { RTTHREADTYPE_INVALID,                 INT_MIN, INT_MIN },
     142            { RTTHREADTYPE_INFREQUENT_POLLER,       30, 30 },
     143            { RTTHREADTYPE_MAIN_HEAVY_WORKER,       31, 31 },
     144            { RTTHREADTYPE_EMULATION,               32, 32 },
     145            { RTTHREADTYPE_DEFAULT,                 40, 40 },
     146            { RTTHREADTYPE_GUI,                     41, 41 },
     147            { RTTHREADTYPE_MAIN_WORKER,             43, 43 },
     148            { RTTHREADTYPE_VRDP_IO,                 45, 45 },
     149            { RTTHREADTYPE_DEBUGGER,                47, 47 },
     150            { RTTHREADTYPE_MSG_PUMP,                49, 49 },
     151            { RTTHREADTYPE_IO,                      57, 57 },
     152            { RTTHREADTYPE_TIMER,                   61, 61 }
     153        }
     154    },
     155    /* last */
     156    {
    89157        RTPROCPRIORITY_FLAT, "Flat",
    90158        {
    91             { RTTHREADTYPE_INVALID,                 ~0, ~0 },
    92             { RTTHREADTYPE_INFREQUENT_POLLER,       PRTYC_REGULAR, 0 },
    93             { RTTHREADTYPE_MAIN_HEAVY_WORKER,       PRTYC_REGULAR, 0 },
    94             { RTTHREADTYPE_EMULATION,               PRTYC_REGULAR, 0 },
    95             { RTTHREADTYPE_DEFAULT,                 PRTYC_REGULAR, 0 },
    96             { RTTHREADTYPE_GUI,                     PRTYC_REGULAR, 0 },
    97             { RTTHREADTYPE_MAIN_WORKER,             PRTYC_REGULAR, 0 },
    98             { RTTHREADTYPE_VRDP_IO,                 PRTYC_REGULAR, 0 },
    99             { RTTHREADTYPE_DEBUGGER,                PRTYC_REGULAR, 0 },
    100             { RTTHREADTYPE_MSG_PUMP,                PRTYC_REGULAR, 0 },
    101             { RTTHREADTYPE_IO,                      PRTYC_REGULAR, 0 },
    102             { RTTHREADTYPE_TIMER,                   PRTYC_REGULAR, 0 }
     159            { RTTHREADTYPE_INVALID,                 INT_MIN, INT_MIN },
     160            { RTTHREADTYPE_INFREQUENT_POLLER,       31, 31 },
     161            { RTTHREADTYPE_MAIN_HEAVY_WORKER,       31, 31 },
     162            { RTTHREADTYPE_EMULATION,               31, 31 },
     163            { RTTHREADTYPE_DEFAULT,                 31, 31 },
     164            { RTTHREADTYPE_GUI,                     31, 31 },
     165            { RTTHREADTYPE_MAIN_WORKER,             31, 31 },
     166            { RTTHREADTYPE_VRDP_IO,                 31, 31 },
     167            { RTTHREADTYPE_DEBUGGER,                31, 31 },
     168            { RTTHREADTYPE_MSG_PUMP,                31, 31 },
     169            { RTTHREADTYPE_IO,                      31, 31 },
     170            { RTTHREADTYPE_TIMER,                   31, 31 }
    103171        }
    104172    },
    105     {
    106         RTPROCPRIORITY_LOW, "Low",
    107         {
    108             { RTTHREADTYPE_INVALID,                 ~0 },
    109             { RTTHREADTYPE_INFREQUENT_POLLER,       PRTYC_IDLETIME, 0 },
    110             { RTTHREADTYPE_MAIN_HEAVY_WORKER,       PRTYC_IDLETIME, 0 },
    111             { RTTHREADTYPE_EMULATION,               PRTYC_IDLETIME, 0 },
    112             { RTTHREADTYPE_DEFAULT,                 PRTYC_IDLETIME, 30 },
    113             { RTTHREADTYPE_GUI,                     PRTYC_IDLETIME, 30 },
    114             { RTTHREADTYPE_MAIN_WORKER,             PRTYC_IDLETIME, 30 },
    115             { RTTHREADTYPE_VRDP_IO,                 PRTYC_REGULAR,  0 },
    116             { RTTHREADTYPE_DEBUGGER,                PRTYC_REGULAR,  0 },
    117             { RTTHREADTYPE_MSG_PUMP,                PRTYC_REGULAR,  0 },
    118             { RTTHREADTYPE_IO,                      PRTYC_REGULAR,  0 },
    119             { RTTHREADTYPE_TIMER,                   PRTYC_REGULAR,  0 }
    120         }
    121     },
    122     {
    123         RTPROCPRIORITY_NORMAL, "Normal",
    124         {
    125             { RTTHREADTYPE_INVALID,                 ~0 },
    126             { RTTHREADTYPE_INFREQUENT_POLLER,       PRTYC_IDLETIME, 30 },
    127             { RTTHREADTYPE_MAIN_HEAVY_WORKER,       PRTYC_IDLETIME, 31 },
    128             { RTTHREADTYPE_EMULATION,               PRTYC_REGULAR,  0 },
    129             { RTTHREADTYPE_DEFAULT,                 PRTYC_REGULAR,  5 },
    130             { RTTHREADTYPE_GUI,                     PRTYC_REGULAR,  10 },
    131             { RTTHREADTYPE_MAIN_WORKER,             PRTYC_REGULAR,  12 },
    132             { RTTHREADTYPE_VRDP_IO,                 PRTYC_REGULAR,  15 },
    133             { RTTHREADTYPE_DEBUGGER,                PRTYC_REGULAR,  20 },
    134             { RTTHREADTYPE_MSG_PUMP,                PRTYC_REGULAR,  25 },
    135             { RTTHREADTYPE_IO,                      PRTYC_FOREGROUNDSERVER,  5 },
    136             { RTTHREADTYPE_TIMER,                   PRTYC_TIMECRITICAL, 0 }
    137         }
    138     },
    139     {
    140         RTPROCPRIORITY_HIGH, "High",
    141         {
    142             { RTTHREADTYPE_INVALID,                 ~0 },
    143             { RTTHREADTYPE_INFREQUENT_POLLER,       PRTYC_IDLETIME, 30 },
    144             { RTTHREADTYPE_MAIN_HEAVY_WORKER,       PRTYC_REGULAR,  0 },
    145             { RTTHREADTYPE_EMULATION,               PRTYC_REGULAR,  0 },
    146             { RTTHREADTYPE_DEFAULT,                 PRTYC_REGULAR,  15 },
    147             { RTTHREADTYPE_GUI,                     PRTYC_REGULAR,  20 },
    148             { RTTHREADTYPE_MAIN_WORKER,             PRTYC_REGULAR,  25 },
    149             { RTTHREADTYPE_VRDP_IO,                 PRTYC_REGULAR,  30 },
    150             { RTTHREADTYPE_DEBUGGER,                PRTYC_TIMECRITICAL, 2 },
    151             { RTTHREADTYPE_MSG_PUMP,                PRTYC_TIMECRITICAL, 3 },
    152             { RTTHREADTYPE_IO,                      PRTYC_TIMECRITICAL, 4 },
    153             { RTTHREADTYPE_TIMER,                   PRTYC_TIMECRITICAL, 5 }
    154         }
     173};
     174
     175
     176/**
     177 * The dynamic default priority configuration.
     178 *
     179 * This can be recalulated at runtime depending on what the
     180 * system allow us to do. Presently we don't do this as it seems
     181 * Darwin generally lets us do whatever we want.
     182 *
     183 * @remarks this is the same as "Normal" above.
     184 */
     185static PROCPRIORITY g_aDefaultPriority =
     186{
     187    RTPROCPRIORITY_DEFAULT, "Default",
     188    {
     189        { RTTHREADTYPE_INVALID,                 INT_MIN, INT_MIN },
     190        { RTTHREADTYPE_INFREQUENT_POLLER,       29, 29 },
     191        { RTTHREADTYPE_MAIN_HEAVY_WORKER,       30, 30 },
     192        { RTTHREADTYPE_EMULATION,               31, 31 }, /* the default priority */
     193        { RTTHREADTYPE_DEFAULT,                 32, 32 },
     194        { RTTHREADTYPE_GUI,                     32, 32 },
     195        { RTTHREADTYPE_MAIN_WORKER,             32, 32 },
     196        { RTTHREADTYPE_VRDP_IO,                 39, 39 },
     197        { RTTHREADTYPE_DEBUGGER,                42, 42 },
     198        { RTTHREADTYPE_MSG_PUMP,                47, 47 },
     199        { RTTHREADTYPE_IO,                      52, 52 },
     200        { RTTHREADTYPE_TIMER,                   55, 55 }
    155201    }
    156202};
    157203
    158 /**
    159  * The dynamic default priority configuration.
    160  *
    161  * This can be recalulated at runtime depending on what the
    162  * system allow us to do. Presently we don't do this as it's
    163  * generally not a bit issue on OS/2 hosts.
    164  */
    165 static PROCPRIORITY g_aDefaultPriority =
    166 {
    167     RTPROCPRIORITY_LOW, "Default",
    168     {
    169         { RTTHREADTYPE_INVALID,                 ~0 },
    170         { RTTHREADTYPE_INFREQUENT_POLLER,       PRTYC_IDLETIME, 30 },
    171         { RTTHREADTYPE_MAIN_HEAVY_WORKER,       PRTYC_IDLETIME, 31 },
    172         { RTTHREADTYPE_EMULATION,               PRTYC_REGULAR,  0 },
    173         { RTTHREADTYPE_DEFAULT,                 PRTYC_REGULAR,  5 },
    174         { RTTHREADTYPE_GUI,                     PRTYC_REGULAR,  10 },
    175         { RTTHREADTYPE_MAIN_WORKER,             PRTYC_REGULAR,  12 },
    176         { RTTHREADTYPE_VRDP_IO,                 PRTYC_REGULAR,  15 },
    177         { RTTHREADTYPE_DEBUGGER,                PRTYC_REGULAR,  20 },
    178         { RTTHREADTYPE_MSG_PUMP,                PRTYC_REGULAR,  25 },
    179         { RTTHREADTYPE_IO,                      PRTYC_FOREGROUNDSERVER, 5 },
    180         { RTTHREADTYPE_TIMER,                   PRTYC_TIMECRITICAL, 0 }
    181     }
    182 };
    183 
    184204
    185205/** Pointer to the current priority configuration. */
     
    188208
    189209/**
    190  * Calculate the scheduling properties for all the threads in the default
    191  * process priority, assuming the current thread have the type enmType.
    192  *
    193  * @returns iprt status code.
    194  * @param   enmType     The thread type to be assumed for the current thread.
    195  */
     210 * Get's the priority information for the current thread.
     211 *
     212 * @returns The base priority
     213 */
     214static int rtSchedDarwinGetBasePriority(void)
     215{
     216    /* the base_priority. */
     217    mach_msg_type_number_t              Count = POLICY_TIMESHARE_INFO_COUNT;
     218    struct policy_timeshare_info        TSInfo = {0,0,0,0,0};
     219    kern_return_t                       krc;
     220    krc = thread_info(mach_thread_self(), THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&TSInfo, &Count);
     221    Assert(krc == KERN_SUCCESS);
     222
     223    return TSInfo.base_priority;
     224}
     225
     226
    196227int rtSchedNativeCalcDefaultPriority(RTTHREADTYPE enmType)
    197228{
    198229    Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
     230
     231    /*
     232     * Get the current priority.
     233     */
     234    int iBasePriority = rtSchedDarwinGetBasePriority();
     235    Assert(iBasePriority >= 0 && iBasePriority <= 63);
     236
     237    /*
     238     * If it doesn't match the default, select the closest one from the table.
     239     */
     240    int iCurDiff = RT_ABS(g_pProcessPriority->aTypes[enmType].iBasePriority - iBasePriority);
     241    if (iCurDiff)
     242    {
     243        const PROCPRIORITY *pProcessPriority = &g_aDefaultPriority;
     244        for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
     245        {
     246            int iBasePriority = RT_ABS(g_aPriorities[i].aTypes[enmType].iBasePriority - iBasePriority);
     247            if (iBasePriority < iCurDiff)
     248            {
     249                g_pProcessPriority = &g_aPriorities[i];
     250                if (!iCurDiff)
     251                    break;
     252                iCurDiff = iBasePriority;
     253            }
     254        }
     255    }
     256
    199257    return VINF_SUCCESS;
    200258}
    201259
    202260
    203 /**
    204  * Validates and sets the process priority.
    205  * This will check that all rtThreadNativeSetPriority() will success for all the
    206  * thread types when applied to the current thread.
    207  *
    208  * @returns iprt status code.
    209  * @param   enmPriority     The priority to validate and set.
    210  * @remark  Located in sched.
    211  */
    212261int rtProcNativeSetPriority(RTPROCPRIORITY enmPriority)
    213262{
    214263    Assert(enmPriority > RTPROCPRIORITY_INVALID && enmPriority < RTPROCPRIORITY_LAST);
     264
     265    /*
     266     * No checks necessary, we assume we can set any priority in the user process range.
     267     */
     268    const PROCPRIORITY *pProcessPriority = &g_aDefaultPriority;
     269    for (unsigned i = 0; i < RT_ELEMENTS(g_aPriorities); i++)
     270        if (g_aPriorities[i].enmPriority == enmPriority)
     271        {
     272            pProcessPriority = &g_aPriorities[i];
     273            break;
     274        }
     275    Assert(pProcessPriority != &g_aDefaultPriority);
     276    ASMAtomicUoWritePtr((void **)&g_pProcessPriority, pProcessPriority);
     277
    215278    return VINF_SUCCESS;
    216279}
    217280
    218281
    219 /**
    220  * Sets the priority of the thread according to the thread type
    221  * and current process priority.
    222  *
    223  * The RTTHREADINT::enmType member has not yet been updated and will be updated by
    224  * the caller on a successful return.
    225  *
    226  * @returns iprt status code.
    227  * @param   pThread     The thread in question.
    228  * @param   enmType     The thread type.
    229  * @remark  Located in sched.
    230  */
    231282int rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType)
    232283{
     284    Assert(pThread->Core.Key == pthread_self());
    233285    Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END);
    234286    AssertMsg(g_pProcessPriority && g_pProcessPriority->aTypes[enmType].enmType == enmType,
    235287              ("enmType=%d entry=%d\n", enmType, g_pProcessPriority->aTypes[enmType].enmType));
    236288
    237 #ifdef OS2_SCHED_ENABLED
    238     APIRET rc = DosSetPriority(PRTYS_THREAD, g_pProcessPriority->aTypes[enmType].ulClass, g_pProcessPriority->aTypes[enmType].ulDelta, (ULONG)pThread->Core.Key & 0xffff /*tid*/);
    239     AssertMsg(rc == NO_ERROR, ("%d\n", rc));
    240     return RTErrConvertFromOS2(rc);
    241 #else
    242     return VINF_SUCCESS;
    243 #endif
     289    /*
     290     * Get the current policy and params first since there are
     291     * opaque members in the param structure and we don't wish to
     292     * change the policy.
     293     */
     294    int iSchedPolicy = SCHED_OTHER;
     295    struct sched_param SchedParam = {0, {0,0,0,0} };
     296    int err = pthread_getschedparam((pthread_t)pThread->Core.Key, &iSchedPolicy, &SchedParam);
     297    if (!err)
     298    {
     299        int const iDesiredBasePriority = g_pProcessPriority->aTypes[enmType].iBasePriority;
     300        int       iPriority            = g_pProcessPriority->aTypes[enmType].iPriority;
     301
     302        /*
     303         * First try with the given pthread priority number.
     304         * Then make adjustments in case we missed the desired base priority (interface
     305         * changed or whatever - its using an obsolete mach api).
     306         */
     307        SchedParam.sched_priority = iPriority;
     308        err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
     309        if (!err)
     310        {
     311            int i = 0;
     312            int iBasePriority = rtSchedDarwinGetBasePriority();
     313
     314            while (!err && iBasePriority < iDesiredBasePriority && i++ < 256)
     315            {
     316                SchedParam.sched_priority = ++iPriority;
     317                err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
     318                iBasePriority = rtSchedDarwinGetBasePriority();
     319            }
     320
     321            while (!err && iBasePriority > iDesiredBasePriority && i++ < 256)
     322            {
     323                SchedParam.sched_priority = --iPriority;
     324                err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam);
     325                iBasePriority = rtSchedDarwinGetBasePriority();
     326            }
     327        }
     328    }
     329    int rc = RTErrConvertFromErrno(err);
     330    AssertMsgRC(rc, ("rc=%Rrc err=%d iSchedPolicy=%d sched_priority=%d\n",
     331                     rc, err, iSchedPolicy, SchedParam.sched_priority));
     332    return rc;
    244333}
    245334
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette