Changeset 77910 in vbox for trunk/src/VBox/Runtime/r3
- Timestamp:
- Mar 27, 2019 11:33:01 AM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 129623
- Location:
- trunk/src/VBox/Runtime/r3
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/darwin/sched-darwin.cpp
r76553 r77910 99 99 { 100 100 { 101 RTPROCPRIORITY_DEFAULT, "Default", 102 { 103 { RTTHREADTYPE_INVALID, INT_MIN, INT_MIN }, 104 { RTTHREADTYPE_INFREQUENT_POLLER, 29, 29 }, 105 { RTTHREADTYPE_MAIN_HEAVY_WORKER, 30, 30 }, 106 { RTTHREADTYPE_EMULATION, 31, 31 }, /* the default priority */ 107 { RTTHREADTYPE_DEFAULT, 32, 32 }, 108 { RTTHREADTYPE_GUI, 32, 32 }, 109 { RTTHREADTYPE_MAIN_WORKER, 32, 32 }, 110 { RTTHREADTYPE_VRDP_IO, 39, 39 }, 111 { RTTHREADTYPE_DEBUGGER, 42, 42 }, 112 { RTTHREADTYPE_MSG_PUMP, 47, 47 }, 113 { RTTHREADTYPE_IO, 52, 52 }, 114 { RTTHREADTYPE_TIMER, 55, 55 } 115 } 116 }, 117 { 101 118 RTPROCPRIORITY_LOW, "Low", 102 119 { … … 207 224 * 208 225 * @returns The base priority 209 */ 210 static int rtSchedDarwinGetBasePriority(void) 226 * @param pThread The thread to get it for. NULL for current. 227 */ 228 static int rtSchedDarwinGetBasePriority(PRTTHREADINT pThread) 211 229 { 212 230 /* the base_priority. */ 213 mach_msg_type_number_t Count= POLICY_TIMESHARE_INFO_COUNT;214 struct policy_timeshare_info 215 kern_return_t krc;216 krc = thread_info(mach_thread_self(),THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&TSInfo, &Count);231 mach_msg_type_number_t Count = POLICY_TIMESHARE_INFO_COUNT; 232 struct policy_timeshare_info TSInfo = {0,0,0,0,0}; 233 kern_return_t krc = thread_info(!pThread ? mach_thread_self() : pthread_mach_thread_np((pthread_t)pThread->Core.Key), 234 THREAD_SCHED_TIMESHARE_INFO, (thread_info_t)&TSInfo, &Count); 217 235 Assert(krc == KERN_SUCCESS); 218 236 … … 228 246 * Get the current priority. 229 247 */ 230 int iBasePriority = rtSchedDarwinGetBasePriority( );248 int iBasePriority = rtSchedDarwinGetBasePriority(NULL); 231 249 Assert(iBasePriority >= 0 && iBasePriority <= 63); 232 250 … … 277 295 DECLHIDDEN(int) rtThreadNativeSetPriority(PRTTHREADINT pThread, RTTHREADTYPE enmType) 278 296 { 279 Assert(pThread->Core.Key == pthread_self());280 297 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END); 281 298 AssertMsg(g_pProcessPriority && g_pProcessPriority->aTypes[enmType].enmType == enmType, … … 305 322 { 306 323 int i = 0; 307 int iBasePriority = rtSchedDarwinGetBasePriority(); 308 309 while (!err && iBasePriority < iDesiredBasePriority && i++ < 256) 324 int iBasePriority = rtSchedDarwinGetBasePriority(pThread); 325 326 while ( !err 327 && iBasePriority < iDesiredBasePriority 328 && i++ < 256) 310 329 { 311 330 SchedParam.sched_priority = ++iPriority; 312 331 err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam); 313 iBasePriority = rtSchedDarwinGetBasePriority( );332 iBasePriority = rtSchedDarwinGetBasePriority(pThread); 314 333 } 315 334 316 while (!err && iBasePriority > iDesiredBasePriority && i++ < 256) 335 while ( !err 336 && iPriority > 0 337 && iBasePriority > iDesiredBasePriority 338 && i++ < 256) 317 339 { 318 340 SchedParam.sched_priority = --iPriority; 319 341 err = pthread_setschedparam((pthread_t)pThread->Core.Key, iSchedPolicy, &SchedParam); 320 iBasePriority = rtSchedDarwinGetBasePriority( );342 iBasePriority = rtSchedDarwinGetBasePriority(pThread); 321 343 } 344 345 return VINF_SUCCESS; 322 346 } 323 347 } -
trunk/src/VBox/Runtime/r3/linux/sched-linux.cpp
r76553 r77910 120 120 int iPthreadPolicy; 121 121 } SAVEDPRIORITY, *PSAVEDPRIORITY; 122 123 124 /** 125 * Priorities for checking by separate thread 126 * @internal 127 */ 128 typedef struct 129 { 130 /** The current thread priority to assume first. */ 131 int iCurrent; 132 /** The thread priority to try set afterwards. */ 133 int iNew; 134 } VALIDATORPRIORITYPAIR, *PVALIDATORPRIORITYPAIR; 122 135 123 136 … … 306 319 307 320 /** 321 * Called on the priority proxy thread if requested running, otherwise 322 * rtSchedRunThread() calls it directly. 323 */ 324 static DECLCALLBACK(int) rtSchedRunThreadCallback(pthread_t *pThread, void *(*pfnThread)(void *pvArg), void *pvArg) 325 { 326 int rc = pthread_create(pThread, NULL, pfnThread, pvArg); 327 if (!rc) 328 return VINF_SUCCESS; 329 return RTErrConvertFromErrno(rc); 330 } 331 332 333 /** 308 334 * Starts a worker thread and wait for it to complete. 335 * 309 336 * We cannot use RTThreadCreate since we're already owner of the RW lock. 310 337 */ 311 static int rtSchedRunThread(void *(*pfnThread)(void *pvArg), void *pvArg )338 static int rtSchedRunThread(void *(*pfnThread)(void *pvArg), void *pvArg, bool fUsePriorityProxy) 312 339 { 313 340 /* … … 315 342 */ 316 343 pthread_t Thread; 317 int rc = pthread_create(&Thread, NULL, pfnThread, pvArg); 318 if (!rc) 344 int rc; 345 #ifndef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 346 RT_NOREF(fUsePriorityProxy); 347 #else 348 if ( fUsePriorityProxy 349 && rtThreadPosixPriorityProxyStart()) 350 rc = rtThreadPosixPriorityProxyCall(NULL, (PFNRT)rtSchedRunThreadCallback, 3, &Thread, pfnThread, pvArg); 351 else 352 #endif 353 rc = rtSchedRunThreadCallback(&Thread, pfnThread, pvArg); 354 if (RT_SUCCESS(rc)) 319 355 { 320 356 /* … … 330 366 return (int)(uintptr_t)pvRet; 331 367 } 332 return RTErrConvertFromErrno(rc);368 return rc; 333 369 } 334 370 … … 435 471 && iStart != g_iMinPriority) 436 472 { 437 if (rtSchedRunThread(rtSchedNativeSubProberThread, (void *)(intptr_t)iStart ) == 0)473 if (rtSchedRunThread(rtSchedNativeSubProberThread, (void *)(intptr_t)iStart, false /*fUsePriorityProxy*/) == 0) 438 474 g_fScrewedUpMaxPriorityLimitInheritance = false; 439 475 } … … 465 501 /** @todo */ 466 502 #endif 467 int rc = rtSchedRunThread(rtSchedNativeProberThread, NULL );503 int rc = rtSchedRunThread(rtSchedNativeProberThread, NULL, false /*fUsePriorityProxy*/); 468 504 if (RT_FAILURE(rc)) 469 505 return rc; … … 499 535 static void *rtSchedNativeValidatorThread(void *pvUser) 500 536 { 501 const PROCPRIORITY *pCfg = (const PROCPRIORITY *)pvUser;537 PVALIDATORPRIORITYPAIR pPrioPair = (PVALIDATORPRIORITYPAIR)pvUser; 502 538 SAVEDPRIORITY SavedPriority; 503 539 rtSchedNativeSave(&SavedPriority); 504 540 505 /*506 * Try out the priorities from the top and down.507 */508 541 int rc = VINF_SUCCESS; 542 543 /* 544 * Set the priority to the current value for specified thread type 545 */ 546 if (setpriority(PRIO_PROCESS, 0, pPrioPair->iCurrent)) 547 rc = RTErrConvertFromErrno(errno); 548 549 /* 550 * Try set the new priority. 551 */ 552 if (RT_SUCCESS(rc) && setpriority(PRIO_PROCESS, 0, pPrioPair->iNew)) 553 rc = RTErrConvertFromErrno(errno); 554 555 /* done */ 556 rtSchedNativeRestore(&SavedPriority); 557 return (void *)(intptr_t)rc; 558 } 559 560 561 /** 562 * Validates the ability to apply suggested priority scheme. 563 * 564 * The function checks that we're able to apply all the thread types in the 565 * suggested priority scheme. 566 * 567 * @returns iprt status code. 568 * @param pCfg The priority scheme to validate. 569 * @param fHavePriorityProxy Set if we've got a priority proxy thread, 570 * otherwise clear. 571 */ 572 static int rtSchedNativeCheckThreadTypes(const PROCPRIORITY *pCfg, bool fHavePriorityProxy) 573 { 574 /** @todo Only check transitions of thread types that actually are in use. 575 * For the others, just check we can create threads with the new priority 576 * scheme (ignoring the old). Best done by having an array of 577 * per-threadtype counters in common/misc/thread.cpp. */ 509 578 int i = RTTHREADTYPE_END; 510 579 while (--i > RTTHREADTYPE_INVALID) 511 580 { 512 int iPriority = pCfg->paTypes[i].iPriority + pCfg->iDelta; 513 if (setpriority(PRIO_PROCESS, 0, iPriority)) 514 { 515 rc = RTErrConvertFromErrno(errno); 516 break; 517 } 581 VALIDATORPRIORITYPAIR PrioPair; 582 PrioPair.iCurrent = g_pProcessPriority->paTypes[i].iPriority + g_pProcessPriority->iDelta; 583 PrioPair.iNew = pCfg->paTypes[i].iPriority + pCfg->iDelta; 584 585 #ifdef RT_STRICT 586 int const iPriority = getpriority(PRIO_PROCESS, 0); 587 #endif 588 int rc = rtSchedRunThread(rtSchedNativeValidatorThread, &PrioPair, fHavePriorityProxy /*fUsePriorityProxy*/); 589 Assert(getpriority(PRIO_PROCESS, 0) == iPriority); 590 591 if (RT_FAILURE(rc)) 592 return rc; 518 593 } 519 520 /* done */ 521 rtSchedNativeRestore(&SavedPriority); 522 return (void *)(intptr_t)rc; 594 return VINF_SUCCESS; 523 595 } 524 596 … … 537 609 Assert(enmPriority > RTPROCPRIORITY_INVALID && enmPriority < RTPROCPRIORITY_LAST); 538 610 539 int rc = VINF_SUCCESS; 611 #ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 612 /* 613 * Make sure the proxy creation thread is started so we don't 'lose' our 614 * initial priority if it's lowered. 615 */ 616 bool const fHavePriorityProxy = rtThreadPosixPriorityProxyStart(); 617 #else 618 bool const fHavePriorityProxy = false; 619 #endif 620 621 int rc; 540 622 if (enmPriority == RTPROCPRIORITY_DEFAULT) 541 g_pProcessPriority = &g_aDefaultPriority; 623 { 624 /* 625 * If we've lowered priority since the process started, it may be impossible 626 * to raise it again for existing thread (new threads will work fine). 627 */ 628 rc = SchedNativeCheckThreadTypes(&g_aDefaultPriority); 629 if (RT_SUCCESS(rc)) 630 g_pProcessPriority = &g_aDefaultPriority; 631 } 542 632 else 543 633 { … … 545 635 * Find a configuration which matches and can be applied. 546 636 */ 547 rc = VERR_ FILE_NOT_FOUND;637 rc = VERR_NOT_FOUND; 548 638 for (unsigned i = 0; i < RT_ELEMENTS(g_aUnixConfigs); i++) 549 {550 639 if (g_aUnixConfigs[i].enmPriority == enmPriority) 551 640 { 552 int iPriority = getpriority(PRIO_PROCESS, 0); 553 int rc3 = rtSchedRunThread(rtSchedNativeValidatorThread, (void *)&g_aUnixConfigs[i]); 554 Assert(getpriority(PRIO_PROCESS, 0) == iPriority); NOREF(iPriority); 555 if (RT_SUCCESS(rc3)) 641 int rc2 = rtSchedNativeCheckThreadTypes(&g_aUnixConfigs[i], fHavePriorityProxy); 642 if (RT_SUCCESS(rc2)) 556 643 { 557 644 g_pProcessPriority = &g_aUnixConfigs[i]; … … 559 646 break; 560 647 } 561 if (rc == VERR_ FILE_NOT_FOUND)562 rc = rc 3;648 if (rc == VERR_NOT_FOUND || rc == VERR_ACCESS_DENIED) 649 rc = rc2; 563 650 } 564 }565 651 } 566 652 … … 574 660 575 661 /** 662 * Called on the priority proxy thread if it's running, otherwise 663 * rtThreadNativeSetPriority calls it directly. 664 */ 665 static DECLCALLBACK(int) rtThreadLinuxSetPriorityCallback(PRTTHREADINT pThread, int iPriority) 666 { 667 if (!setpriority(PRIO_PROCESS, pThread->tid, iPriority)) 668 { 669 AssertMsg(iPriority == getpriority(PRIO_PROCESS, pThread->tid), 670 ("iPriority=%d getpriority()=%d\n", iPriority, getpriority(PRIO_PROCESS, pThread->tid))); 671 #ifdef THREAD_LOGGING 672 Log(("rtThreadNativeSetPriority: Thread=%p enmType=%d iPriority=%d pid=%d tid=%d\n", 673 pThread->Core.Key, enmType, iPriority, getpid(), pThread->tid)); 674 #endif 675 return VINF_SUCCESS; 676 } 677 AssertMsgFailed(("setpriority(,, %d) -> errno=%d rc=%Rrc\n", iPriority, errno, RTErrConvertFromErrno(errno))); 678 return VINF_SUCCESS; //non-fatal for now. 679 } 680 681 682 /** 576 683 * Sets the priority of the thread according to the thread type 577 684 * and current process priority. … … 589 696 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END); 590 697 Assert(enmType == g_pProcessPriority->paTypes[enmType].enmType); 591 Assert((pthread_t)pThread->Core.Key == pthread_self()); RT_NOREF_PV(pThread); 592 593 /* 594 * Calculate the thread priority and apply it. 595 */ 596 int rc = VINF_SUCCESS; 597 int iPriority = g_pProcessPriority->paTypes[enmType].iPriority + g_pProcessPriority->iDelta; 598 if (!setpriority(PRIO_PROCESS, 0, iPriority)) 599 { 600 AssertMsg(iPriority == getpriority(PRIO_PROCESS, 0), ("iPriority=%d getpriority()=%d\n", iPriority, getpriority(PRIO_PROCESS, 0))); 601 #ifdef THREAD_LOGGING 602 Log(("rtThreadNativeSetPriority: Thread=%p enmType=%d iPriority=%d pid=%d\n", pThread->Core.Key, enmType, iPriority, getpid())); 603 #endif 604 } 605 else 606 { 607 rc = RTErrConvertFromErrno(errno); 608 AssertMsgFailed(("setpriority(,, %d) -> errno=%d rc=%Rrc\n", iPriority, errno, rc)); 609 rc = VINF_SUCCESS; //non-fatal for now. 610 } 611 612 return rc; 613 } 614 698 699 /* 700 * The thread ID is zero for alien threads, so skip these or we'd risk 701 * modifying our own priority. 702 */ 703 if (!pThread->tid) 704 return VINF_SUCCESS; 705 706 /* 707 * Calculate the thread priority and apply it, preferrably via the priority proxy thread. 708 */ 709 int const iPriority = g_pProcessPriority->paTypes[enmType].iPriority + g_pProcessPriority->iDelta; 710 #ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 711 if (rtThreadPosixPriorityProxyStart()) 712 return rtThreadPosixPriorityProxyCall(pThread, (PFNRT)rtThreadLinuxSetPriorityCallback, 2, pThread, iPriority); 713 #endif 714 return rtThreadLinuxSetPriorityCallback(pThread, iPriority); 715 } 716 -
trunk/src/VBox/Runtime/r3/posix/sched-posix.cpp
r76553 r77910 323 323 /** Set if we figure we have nice capability, meaning we can use setpriority 324 324 * to raise the priority. */ 325 bool g_fCanNice = false;325 static bool g_fCanNice = false; 326 326 327 327 … … 500 500 /* done */ 501 501 rtSchedNativeRestore(&SavedPriority); 502 RT_NOREF(pvUser); 502 503 return (void *)VINF_SUCCESS; 503 504 } … … 634 635 /* done */ 635 636 rtSchedNativeRestore(&SavedPriority); 636 return (void *) rc;637 return (void *)(intptr_t)rc; 637 638 } 638 639 … … 650 651 Assert(enmPriority > RTPROCPRIORITY_INVALID && enmPriority < RTPROCPRIORITY_LAST); 651 652 653 #ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 654 /* 655 * Make sure the proxy creation thread is started so we don't 'lose' our 656 * initial priority if it's lowered. 657 */ 658 rtThreadPosixPriorityProxyStart(); 659 #endif 660 661 /* 662 * Nothing to validate for the default priority (assuming no external renice). 663 */ 652 664 int rc = VINF_SUCCESS; 653 665 if (enmPriority == RTPROCPRIORITY_DEFAULT) … … 732 744 733 745 /** 746 * Worker for rtThreadNativeSetPriority/OSPRIOSUP_PROCESS_AND_THREAD_LEVEL 747 * that's either called on the priority proxy thread or directly if no proxy. 748 */ 749 static DECLCALLBACK(int) rtThreadPosixSetPriorityOnProcAndThrdCallback(PRTTHREADINT pThread, RTTHREADTYPE enmType) 750 { 751 struct sched_param SchedParam = {-9999999}; 752 int iPolicy = -7777777; 753 int rc = pthread_getschedparam((pthread_t)pThread->Core.Key, &iPolicy, &SchedParam); 754 if (!rc) 755 { 756 SchedParam.sched_priority = g_pProcessPriority->paTypes[enmType].iPriority 757 + g_pProcessPriority->iDelta 758 + sched_get_priority_min(iPolicy); 759 760 rc = pthread_setschedparam((pthread_t)pThread->Core.Key, iPolicy, &SchedParam); 761 if (!rc) 762 { 763 #ifdef THREAD_LOGGING 764 Log(("rtThreadNativeSetPriority: Thread=%p enmType=%d iPolicy=%d sched_priority=%d pid=%d\n", 765 pThread->Core.Key, enmType, iPolicy, SchedParam.sched_priority, getpid())); 766 #endif 767 return VINF_SUCCESS; 768 } 769 } 770 771 int rcNative = rc; 772 rc = RTErrConvertFromErrno(rc); 773 AssertMsgFailed(("pthread_[gs]etschedparam(%p, %d, {%d}) -> rcNative=%d rc=%Rrc\n", 774 (void *)pThread->Core.Key, iPolicy, SchedParam.sched_priority, rcNative, rc)); NOREF(rcNative); 775 return rc; 776 } 777 778 779 /** 734 780 * Sets the priority of the thread according to the thread type 735 781 * and current process priority. … … 746 792 Assert(enmType > RTTHREADTYPE_INVALID && enmType < RTTHREADTYPE_END); 747 793 Assert(enmType == g_pProcessPriority->paTypes[enmType].enmType); 748 Assert((pthread_t)pThread->Core.Key == pthread_self());749 794 750 795 int rc = VINF_SUCCESS; … … 753 798 case OSPRIOSUP_PROCESS_AND_THREAD_LEVEL: 754 799 { 755 struct sched_param SchedParam = {-9999999}; 756 int iPolicy = -7777777; 757 pthread_t Self = pthread_self(); 758 rc = pthread_getschedparam(Self, &iPolicy, &SchedParam); 759 if (!rc) 760 { 761 SchedParam.sched_priority = g_pProcessPriority->paTypes[enmType].iPriority 762 + g_pProcessPriority->iDelta 763 + sched_get_priority_min(iPolicy); 764 rc = pthread_setschedparam(Self, iPolicy, &SchedParam); 765 if (!rc) 766 { 767 #ifdef THREAD_LOGGING 768 Log(("rtThreadNativeSetPriority: Thread=%p enmType=%d iPolicy=%d sched_priority=%d pid=%d\n", 769 pThread->Core.Key, enmType, iPolicy, SchedParam.sched_priority, getpid())); 800 #ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 801 if (rtThreadPosixPriorityProxyStart()) 802 rc = rtThreadPosixPriorityProxyCall(pThread, (PFNRT)rtThreadPosixSetPriorityOnProcAndThrdCallback, 803 2, pThread, enmType); 804 else 770 805 #endif 771 break; 772 } 773 } 774 775 int rcNative = rc; 776 rc = RTErrConvertFromErrno(rc); 777 AssertMsgFailed(("pthread_[gs]etschedparam(%p, %d, {%d}) -> rcNative=%d rc=%Rrc\n", 778 (void *)Self, iPolicy, SchedParam.sched_priority, rcNative, rc)); NOREF(rcNative); 806 rc = rtThreadPosixSetPriorityOnProcAndThrdCallback(pThread, enmType); 779 807 break; 780 808 } … … 782 810 case OSPRIOSUP_THREAD_LEVEL: 783 811 { 812 /* No cross platform way of getting the 'who' parameter value for 813 arbitrary threads, so this is restricted to the calling thread only. */ 814 AssertReturn((pthread_t)pThread->Core.Key == pthread_self(), VERR_NOT_SUPPORTED); 815 784 816 int iPriority = g_pProcessPriority->paTypes[enmType].iPriority + g_pProcessPriority->iDelta; 785 817 if (!setpriority(PRIO_PROCESS, 0, iPriority)) -
trunk/src/VBox/Runtime/r3/posix/thread-posix.cpp
r76553 r77910 33 33 #include <pthread.h> 34 34 #include <signal.h> 35 #include <stdlib.h> 35 36 #if defined(RT_OS_LINUX) 36 37 # include <unistd.h> … … 65 66 #include <iprt/initterm.h> 66 67 #include <iprt/string.h> 68 #include <iprt/semaphore.h> 69 #include <iprt/list.h> 70 #include <iprt/once.h> 71 #include <iprt/critsect.h> 72 #include <iprt/req.h> 67 73 #include "internal/thread.h" 68 74 … … 111 117 static PFNPTHREADSETNAME g_pfnThreadSetName = NULL; 112 118 #endif /* IPRT_MAY_HAVE_PTHREAD_SET_NAME_NP */ 119 120 #ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 121 /** Atomic indicator of whether the priority proxy thread has been (attempted) started. 122 * 123 * The priority proxy thread is started under these circumstances: 124 * - RTThreadCreate 125 * - RTThreadSetType 126 * - RTProcSetPriority 127 * 128 * Which means that we'll be single threaded when this is modified. 129 * 130 * Speical values: 131 * - VERR_TRY_AGAIN: Not yet started. 132 * - VERR_WRONG_ORDER: Starting. 133 * - VINF_SUCCESS: Started successfully. 134 * - VERR_PROCESS_NOT_FOUND: Stopping or stopped 135 * - Other error status if failed to start. 136 * 137 * @note We could potentially optimize this by only start it when we lower the 138 * priority of ourselves, the process, or a newly created thread. But 139 * that would means we would need to take multi-threading into account, so 140 * let's not do that for now. 141 */ 142 static int32_t volatile g_rcPriorityProxyThreadStart = VERR_TRY_AGAIN; 143 /** The IPRT thread handle for the priority proxy. */ 144 static RTTHREAD g_hRTThreadPosixPriorityProxyThread = NIL_RTTHREAD; 145 /** The priority proxy queue. */ 146 static RTREQQUEUE g_hRTThreadPosixPriorityProxyQueue = NIL_RTREQQUEUE; 147 #endif /* RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY */ 113 148 114 149 … … 332 367 } 333 368 334 335 DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread) 369 #ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 370 371 /** 372 * @callback_method_impl{FNRTTHREAD, 373 * Priority proxy thread that services g_hRTThreadPosixPriorityProxyQueue.} 374 */ 375 static DECLCALLBACK(int) rtThreadPosixPriorityProxyThread(PRTTHREADINT, void *) 376 { 377 for (;;) 378 { 379 RTREQQUEUE hReqQueue = g_hRTThreadPosixPriorityProxyQueue; 380 if (hReqQueue != NIL_RTREQQUEUE) 381 RTReqQueueProcess(hReqQueue, RT_INDEFINITE_WAIT); 382 else 383 break; 384 385 int32_t rc = ASMAtomicUoReadS32(&g_rcPriorityProxyThreadStart); 386 if (rc != VINF_SUCCESS && rc != VERR_WRONG_ORDER) 387 break; 388 } 389 390 return VINF_SUCCESS; 391 } 392 393 394 /** 395 * Just returns a non-success status codes to force the thread to re-evaluate 396 * the global shutdown variable. 397 */ 398 static DECLCALLBACK(int) rtThreadPosixPriorityProxyStopper(void) 399 { 400 return VERR_CANCELLED; 401 } 402 403 404 /** 405 * An atexit() callback that stops the proxy creation/priority thread. 406 */ 407 static void rtThreadStopProxyThread(void) 408 { 409 /* 410 * Signal to the thread that it's time to shut down. 411 */ 412 int32_t rc = ASMAtomicXchgS32(&g_rcPriorityProxyThreadStart, VERR_PROCESS_NOT_FOUND); 413 if (RT_SUCCESS(rc)) 414 { 415 /* 416 * Grab the associated handles. 417 */ 418 RTTHREAD hThread = g_hRTThreadPosixPriorityProxyThread; 419 RTREQQUEUE hQueue = g_hRTThreadPosixPriorityProxyQueue; 420 g_hRTThreadPosixPriorityProxyQueue = NIL_RTREQQUEUE; 421 g_hRTThreadPosixPriorityProxyThread = NIL_RTTHREAD; 422 ASMCompilerBarrier(); /* paranoia */ 423 424 AssertReturnVoid(hThread != NIL_RTTHREAD); 425 AssertReturnVoid(hQueue != NIL_RTREQQUEUE); 426 427 /* 428 * Kick the thread so it gets out of any pending RTReqQueueProcess call ASAP. 429 */ 430 rc = RTReqQueueCallEx(hQueue, NULL, 0 /*cMillies*/, RTREQFLAGS_IPRT_STATUS | RTREQFLAGS_NO_WAIT, 431 (PFNRT)rtThreadPosixPriorityProxyStopper, 0); 432 433 /* 434 * Wait for the thread to complete. 435 */ 436 rc = RTThreadWait(hThread, RT_SUCCESS(rc) ? RT_MS_1SEC * 5 : 32, NULL); 437 if (RT_SUCCESS(rc)) 438 RTReqQueueDestroy(hQueue); 439 /* else: just leak the stuff, we're exitting, so nobody cares... */ 440 } 441 } 442 443 444 /** 445 * Ensure that the proxy priority proxy thread has been started. 446 * 447 * Since we will always start a proxy thread when asked to create a thread, 448 * there is no need for serialization here. 449 * 450 * @retval true if started 451 * @retval false if it failed to start (caller must handle this scenario). 452 */ 453 DECLHIDDEN(bool) rtThreadPosixPriorityProxyStart(void) 454 { 455 /* 456 * Read the result. 457 */ 458 int rc = ASMAtomicUoReadS32(&g_rcPriorityProxyThreadStart); 459 if (rc != VERR_TRY_AGAIN) 460 return RT_SUCCESS(rc); 461 462 /* If this triggers then there is a very unexpected race somewhere. It 463 should be harmless though. */ 464 AssertReturn(ASMAtomicCmpXchgS32(&g_rcPriorityProxyThreadStart, VERR_WRONG_ORDER, VERR_TRY_AGAIN), false); 465 466 /* 467 * Not yet started, so do that. 468 */ 469 rc = RTReqQueueCreate(&g_hRTThreadPosixPriorityProxyQueue); 470 if (RT_SUCCESS(rc)) 471 { 472 rc = RTThreadCreate(&g_hRTThreadPosixPriorityProxyThread, rtThreadPosixPriorityProxyThread, NULL, 0 /*cbStack*/, 473 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "RTThrdPP"); 474 if (RT_SUCCESS(rc)) 475 { 476 ASMAtomicWriteS32(&g_rcPriorityProxyThreadStart, VINF_SUCCESS); 477 478 atexit(rtThreadStopProxyThread); 479 return true; 480 } 481 RTReqQueueCreate(&g_hRTThreadPosixPriorityProxyQueue); 482 } 483 ASMAtomicWriteS32(&g_rcPriorityProxyThreadStart, rc != VERR_WRONG_ORDER ? rc : VERR_PROCESS_NOT_FOUND); 484 return false; 485 } 486 487 488 /** 489 * Calls @a pfnFunction from the priority proxy thread. 490 * 491 * Caller must have called rtThreadPosixStartProxy() to check that the priority 492 * proxy thread is running. 493 * 494 * @returns 495 * @param pTargetThread The target thread, NULL if not applicable. This is 496 * so we can skip calls pertaining to the priority 497 * proxy thread itself. 498 * @param pfnFunction The function to call. Must return IPRT status code. 499 * @param cArgs Number of arguments (see also RTReqQueueCall). 500 * @param ... Arguments (see also RTReqQueueCall). 501 */ 502 DECLHIDDEN(int) rtThreadPosixPriorityProxyCall(PRTTHREADINT pTargetThread, PFNRT pfnFunction, int cArgs, ...) 503 { 504 int rc; 505 if ( !pTargetThread 506 || pTargetThread->pfnThread != rtThreadPosixPriorityProxyThread) 507 { 508 va_list va; 509 va_start(va, cArgs); 510 PRTREQ pReq; 511 rc = RTReqQueueCallV(g_hRTThreadPosixPriorityProxyQueue, &pReq, RT_INDEFINITE_WAIT, RTREQFLAGS_IPRT_STATUS, 512 pfnFunction, cArgs, va); 513 va_end(va); 514 RTReqRelease(pReq); 515 } 516 else 517 rc = VINF_SUCCESS; 518 return rc; 519 } 520 521 #endif /* !RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY */ 522 523 /** 524 * Worker for rtThreadNativeCreate that's either called on the priority proxy 525 * thread or directly on the calling thread depending on the proxy state. 526 */ 527 static DECLCALLBACK(int) rtThreadNativeInternalCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread) 336 528 { 337 529 /* … … 377 569 378 570 571 DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThread, PRTNATIVETHREAD pNativeThread) 572 { 573 #ifdef RTTHREAD_POSIX_WITH_CREATE_PRIORITY_PROXY 574 /* 575 * If we have a priority proxy thread, use it. Make sure to ignore the 576 * staring of the proxy thread itself. 577 */ 578 if ( pThread->pfnThread != rtThreadPosixPriorityProxyThread 579 && rtThreadPosixPriorityProxyStart()) 580 { 581 PRTREQ pReq; 582 int rc = RTReqQueueCall(g_hRTThreadPosixPriorityProxyQueue, &pReq, RT_INDEFINITE_WAIT, 583 (PFNRT)rtThreadNativeInternalCreate, 2, pThread, pNativeThread); 584 RTReqRelease(pReq); 585 return rc; 586 } 587 588 /* 589 * Fall back on creating it directly without regard to priority proxying. 590 */ 591 #endif 592 return rtThreadNativeInternalCreate(pThread, pNativeThread); 593 } 594 595 379 596 RTDECL(RTTHREAD) RTThreadSelf(void) 380 597 { -
trunk/src/VBox/Runtime/r3/win/sched-win.cpp
r76634 r77910 328 328 329 329 #ifdef WIN32_SCHED_ENABLED 330 if (SetThreadPriority(rtThreadNativeGetHandle(pThread), g_pProcessPriority->aTypes[enmType].iThreadPriority)) 330 HANDLE hThread = rtThreadNativeGetHandle(pThread); 331 if ( hThread == NULL /* No handle for alien threads. */ 332 || SetThreadPriority(hThread, g_pProcessPriority->aTypes[enmType].iThreadPriority)) 331 333 return VINF_SUCCESS; 332 334
Note:
See TracChangeset
for help on using the changeset viewer.