Changeset 15881 in vbox
- Timestamp:
- Jan 8, 2009 6:46:52 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 41492
- Location:
- trunk/src/VBox/Runtime
- Files:
-
- 1 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/Makefile.kmk
r15843 r15881 452 452 generic/RTUuidCreate-generic.cpp \ 453 453 generic/mppresent-generic.cpp \ 454 generic/sched-generic.cpp \455 454 generic/timer-generic.cpp \ 456 455 generic/utf16locale-generic.cpp \ … … 460 459 r3/darwin/mp-darwin.cpp \ 461 460 r3/darwin/rtProcInitExePath-darwin.cpp \ 461 r3/darwin/sched-darwin.cpp \ 462 462 r3/darwin/time-darwin.cpp \ 463 463 r3/posix/RTSystemQueryOSInfo-posix.cpp \ -
trunk/src/VBox/Runtime/r3/darwin/sched-darwin.cpp
r15866 r15881 1 1 /* $Id$ */ 2 2 /** @file 3 * IPRT - Scheduling, OS/23 * IPRT - Scheduling, Darwin. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2006-200 7Sun Microsystems, Inc.7 * Copyright (C) 2006-2009 Sun Microsystems, Inc. 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 29 29 */ 30 30 31 /** @def OS2_SCHED_ENABLED32 * Enables the priority scheme. */33 #define OS2_SCHED_ENABLED34 35 31 36 32 /******************************************************************************* … … 38 34 *******************************************************************************/ 39 35 #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> 43 46 44 47 #include <iprt/thread.h> … … 46 49 #include <iprt/assert.h> 47 50 #include <iprt/err.h> 51 #include <iprt/asm.h> 52 #include <iprt/assert.h> 48 53 #include "internal/sched.h" 49 54 #include "internal/thread.h" … … 67 72 /** For sanity include the array index. */ 68 73 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; 73 79 } aTypes[RTTHREADTYPE_END]; 74 80 } PROCPRIORITY; 75 76 /** Matches any process priority class. */77 #define ANY_PROCESS_PRIORITY_CLASS (~0U)78 81 79 82 … … 83 86 /** 84 87 * 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). 85 101 */ 86 102 static const PROCPRIORITY g_aPriorities[] = 87 103 { 88 104 { 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 { 89 157 RTPROCPRIORITY_FLAT, "Flat", 90 158 { 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 } 103 171 } 104 172 }, 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 */ 185 static 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 } 155 201 } 156 202 }; 157 203 158 /**159 * The dynamic default priority configuration.160 *161 * This can be recalulated at runtime depending on what the162 * system allow us to do. Presently we don't do this as it's163 * 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 184 204 185 205 /** Pointer to the current priority configuration. */ … … 188 208 189 209 /** 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 */ 214 static 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 196 227 int rtSchedNativeCalcDefaultPriority(RTTHREADTYPE enmType) 197 228 { 198 229 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 199 257 return VINF_SUCCESS; 200 258 } 201 259 202 260 203 /**204 * Validates and sets the process priority.205 * This will check that all rtThreadNativeSetPriority() will success for all the206 * 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 */212 261 int rtProcNativeSetPriority(RTPROCPRIORITY enmPriority) 213 262 { 214 263 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 215 278 return VINF_SUCCESS; 216 279 } 217 280 218 281 219 /**220 * Sets the priority of the thread according to the thread type221 * and current process priority.222 *223 * The RTTHREADINT::enmType member has not yet been updated and will be updated by224 * 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 */231 282 int rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType) 232 283 { 284 Assert(pThread->Core.Key == pthread_self()); 233 285 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END); 234 286 AssertMsg(g_pProcessPriority && g_pProcessPriority->aTypes[enmType].enmType == enmType, 235 287 ("enmType=%d entry=%d\n", enmType, g_pProcessPriority->aTypes[enmType].enmType)); 236 288 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; 244 333 } 245 334
Note:
See TracChangeset
for help on using the changeset viewer.