Changeset 25640 in vbox
- Timestamp:
- Jan 4, 2010 4:44:23 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 56342
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/semaphore.h
r25638 r25640 143 143 * @param hThread A previously added thread. 144 144 */ 145 RTDECL(void) RTSemEventRemove rSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread);145 RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread); 146 146 147 147 /** @} */ … … 211 211 */ 212 212 RTDECL(int) RTSemEventMultiWaitNoResume(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies); 213 214 /** 215 * Sets the signaller thread to one specific thread. 216 * 217 * This is only used for validating usage and deadlock detection. When used 218 * after calls to RTSemEventAddSignaller, the specified thread will be the only 219 * signalling thread. 220 * 221 * @param hEventMultiSem The multiple release event semaphore. 222 * @param hThread The thread that will signal it. Pass 223 * NIL_RTTHREAD to indicate that there is no 224 * special signalling thread. 225 */ 226 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread); 227 228 /** 229 * To add more signalling threads. 230 * 231 * First call RTSemEventSetSignaller then add further threads with this. 232 * 233 * @param hEventMultiSem The multiple release event semaphore. 234 * @param hThread The thread that will signal it. NIL_RTTHREAD is 235 * not accepted. 236 */ 237 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread); 238 239 /** 240 * To remove a signalling thread. 241 * 242 * Reverts work done by RTSemEventAddSignaller and RTSemEventSetSignaller. 243 * 244 * @param hEventMultiSem The multiple release event semaphore. 245 * @param hThread A previously added thread. 246 */ 247 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread); 213 248 214 249 /** @} */ -
trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
r22959 r25640 31 31 32 32 #include <features.h> 33 #if __GLIBC_PREREQ(2,6) && !defined(IPRT_WITH_FUTEX_BASED_SEMS) 33 #if __GLIBC_PREREQ(2,6) && !defined(IPRT_WITH_FUTEX_BASED_SEMS) && !defined(DEBUG_bird) 34 34 35 35 /* … … 300 300 } 301 301 302 303 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 304 { 305 /** @todo implement RTSemEventMultiSetSignaller on OS/2 */ 306 } 307 308 309 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 310 { 311 } 312 313 314 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 315 { 316 } 317 302 318 #endif /* glibc < 2.6 || IPRT_WITH_FUTEX_BASED_SEMS */ 303 319 -
trunk/src/VBox/Runtime/r3/os2/sems-os2.cpp
r25638 r25640 136 136 137 137 138 RTDECL(void) RTSemEventRemove rSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)138 RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread) 139 139 { 140 140 … … 313 313 314 314 315 315 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 316 { 317 /** @todo implement RTSemEventMultiSetSignaller on OS/2 */ 318 } 319 320 321 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 322 { 323 } 324 325 326 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 327 { 328 } 329 -
trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
r25636 r25640 33 33 *******************************************************************************/ 34 34 #include <iprt/semaphore.h> 35 #include "internal/iprt.h" 36 37 #include <iprt/asm.h> 35 38 #include <iprt/assert.h> 36 #include <iprt/alloc.h>37 #include <iprt/asm.h>38 39 #include <iprt/err.h> 40 #include <iprt/lockvalidator.h> 41 #include <iprt/mem.h> 42 43 #include "internal/strict.h" 39 44 40 45 #include <errno.h> … … 61 66 /** Number of waiters. */ 62 67 volatile uint32_t cWaiters; 68 #ifdef RTSEMEVENTMULTI_STRICT 69 /** Signallers. */ 70 RTLOCKVALRECSHRD Signallers; 71 /** Indicates that lock validation should be performed. */ 72 bool volatile fEverHadSignallers; 73 #endif 63 74 }; 64 75 … … 73 84 /** @} */ 74 85 75 76 77 /**78 * Validate an event multi semaphore handle passed to one of the interface.79 *80 * @returns true if valid.81 * @returns false if invalid.82 * @param pThis Pointer to the event semaphore to validate.83 */84 inline bool rtsemEventMultiValid(struct RTSEMEVENTMULTIINTERNAL *pThis)85 {86 if ((uintptr_t)pThis < 0x10000)87 return false;88 89 uint32_t u32 = pThis->u32State; /* this is volatile, so a explicit read like this is needed. */90 if ( u32 != EVENTMULTI_STATE_NOT_SIGNALED91 && u32 != EVENTMULTI_STATE_SIGNALED)92 return false;93 94 return true;95 }96 86 97 87 … … 131 121 ASMAtomicXchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED); 132 122 ASMAtomicXchgU32(&pThis->cWaiters, 0); 123 #ifdef RTSEMEVENTMULTI_STRICT 124 RTLockValidatorRecSharedInit(&pThis->Signallers, 125 NIL_RTLOCKVALIDATORCLASS, RTLOCKVALIDATOR_SUB_CLASS_ANY, 126 "RTSemEvent", pThis, true /*fSignaller*/); 127 pThis->fEverHadSignallers = false; 128 #endif 133 129 134 130 *pEventMultiSem = pThis; … … 159 155 * Validate handle. 160 156 */ 161 if (!rtsemEventMultiValid(EventMultiSem)) 162 { 163 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 164 return VERR_INVALID_HANDLE; 165 } 157 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 158 if (pThis == NIL_RTSEMEVENTMULTI) 159 return VINF_SUCCESS; 160 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 161 uint32_t u32 = pThis->u32State; 162 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE); 166 163 167 164 /* 168 165 * Abort all waiters forcing them to return failure. 169 166 */ 170 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;171 167 int rc; 172 168 for (int i = 30; i > 0; i--) … … 205 201 * Free the semaphore memory and be gone. 206 202 */ 203 #ifdef RTSEMEVENTMULTI_STRICT 204 RTLockValidatorRecSharedDelete(&pThis->Signallers); 205 #endif 207 206 RTMemFree(pThis); 208 207 return VINF_SUCCESS; … … 215 214 * Validate input. 216 215 */ 217 if (!rtsemEventMultiValid(EventMultiSem)) 218 { 219 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 220 return VERR_INVALID_HANDLE; 221 } 216 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 217 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 218 uint32_t u32 = pThis->u32State; 219 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE); 220 221 #ifdef RTSEMEVENTMULTI_STRICT 222 if (pThis->fEverHadSignallers) 223 { 224 int rc9 = RTLockValidatorRecSharedCheckSignaller(&pThis->Signallers, NIL_RTTHREAD); 225 if (RT_FAILURE(rc9)) 226 return rc9; 227 } 228 #endif 222 229 223 230 /* 224 231 * Lock the mutex semaphore. 225 232 */ 226 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;227 233 int rc = pthread_mutex_lock(&pThis->Mutex); 228 234 if (rc) … … 268 274 * Validate input. 269 275 */ 270 if (!rtsemEventMultiValid(EventMultiSem)) 271 { 272 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 273 return VERR_INVALID_HANDLE; 274 } 276 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 277 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 278 uint32_t u32 = pThis->u32State; 279 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE); 275 280 276 281 /* 277 282 * Lock the mutex semaphore. 278 283 */ 279 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;280 284 int rc = pthread_mutex_lock(&pThis->Mutex); 281 285 if (rc) … … 310 314 static int rtSemEventMultiWait(RTSEMEVENTMULTI EventMultiSem, unsigned cMillies, bool fAutoResume) 311 315 { 316 PCRTLOCKVALSRCPOS pSrcPos = NULL; 317 312 318 /* 313 319 * Validate input. 314 320 */ 315 if (!rtsemEventMultiValid(EventMultiSem)) 316 { 317 AssertMsgFailed(("Invalid handle %p!\n", EventMultiSem)); 318 return VERR_INVALID_HANDLE; 319 } 321 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem; 322 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 323 uint32_t u32 = pThis->u32State; 324 AssertReturn(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED, VERR_INVALID_HANDLE); 320 325 321 326 /* 322 327 * Timed or indefinite wait? 323 328 */ 324 struct RTSEMEVENTMULTIINTERNAL *pThis = EventMultiSem;325 329 if (cMillies == RT_INDEFINITE_WAIT) 326 330 { … … 352 356 353 357 /* wait */ 358 #ifdef RTSEMEVENTMULTI_STRICT 359 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt(); 360 if (pThis->fEverHadSignallers) 361 { 362 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 363 RTTHREADSTATE_EVENT_MULTI, true); 364 if (RT_FAILURE(rc)) 365 { 366 ASMAtomicDecU32(&pThis->cWaiters); 367 pthread_mutex_unlock(&pThis->Mutex); 368 return rc; 369 } 370 } 371 #else 372 RTTHREAD hThreadSelf = RTThreadSelf(); 373 #endif 374 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true); 354 375 rc = pthread_cond_wait(&pThis->Cond, &pThis->Mutex); 376 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI); 355 377 if (rc) 356 378 { … … 396 418 397 419 /* take mutex */ 398 #ifdef RT_OS_DARWIN399 420 int rc = pthread_mutex_lock(&pThis->Mutex); 400 #else401 int rc = pthread_mutex_timedlock(&pThis->Mutex, &ts);402 #endif403 421 if (rc) 404 422 { … … 425 443 } 426 444 445 /* we're done if the timeout is 0. */ 446 if (!cMillies) 447 { 448 ASMAtomicDecU32(&pThis->cWaiters); 449 rc = pthread_mutex_unlock(&pThis->Mutex); 450 return VERR_SEM_BUSY; 451 } 452 427 453 /* wait */ 454 #ifdef RTSEMEVENTMULTI_STRICT 455 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt(); 456 if (pThis->fEverHadSignallers) 457 { 458 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 459 RTTHREADSTATE_EVENT_MULTI, true); 460 if (RT_FAILURE(rc)) 461 { 462 ASMAtomicDecU32(&pThis->cWaiters); 463 pthread_mutex_unlock(&pThis->Mutex); 464 return rc; 465 } 466 } 467 #else 468 RTTHREAD hThreadSelf = RTThreadSelf(); 469 #endif 470 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true); 428 471 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &ts); 472 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI); 429 473 if (rc && (rc != EINTR || !fAutoResume)) /* according to SuS this function shall not return EINTR, but linux man page says differently. */ 430 474 { … … 453 497 } 454 498 499 500 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 501 { 502 #ifdef RTSEMEVENTMULTI_STRICT 503 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem; 504 AssertPtrReturnVoid(pThis); 505 uint32_t u32 = pThis->u32State; 506 AssertReturnVoid(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED); 507 508 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true); 509 RTLockValidatorRecSharedResetOwner(&pThis->Signallers, hThread, NULL); 510 #endif 511 } 512 513 514 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 515 { 516 #ifdef RTSEMEVENTMULTI_STRICT 517 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem; 518 AssertPtrReturnVoid(pThis); 519 uint32_t u32 = pThis->u32State; 520 AssertReturnVoid(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED); 521 522 ASMAtomicWriteBool(&pThis->fEverHadSignallers, true); 523 RTLockValidatorRecSharedAddOwner(&pThis->Signallers, hThread, NULL); 524 #endif 525 } 526 527 528 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 529 { 530 #ifdef RTSEMEVENTMULTI_STRICT 531 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventMultiSem; 532 AssertPtrReturnVoid(pThis); 533 uint32_t u32 = pThis->u32State; 534 AssertReturnVoid(u32 == EVENTMULTI_STATE_NOT_SIGNALED || u32 == EVENTMULTI_STATE_SIGNALED); 535 536 RTLockValidatorRecSharedRemoveOwner(&pThis->Signallers, hThread); 537 #endif 538 } 539 -
trunk/src/VBox/Runtime/r3/win/semevent-win.cpp
r25638 r25640 137 137 138 138 139 RTDECL(void) RTSemEventRemove rSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread)139 RTDECL(void) RTSemEventRemoveSignaller(RTSEMEVENT hEventSem, RTTHREAD hThread) 140 140 { 141 141 -
trunk/src/VBox/Runtime/r3/win/semeventmulti-win.cpp
r25381 r25640 132 132 } 133 133 134 135 RTDECL(void) RTSemEventMultiSetSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 136 { 137 /** @todo implement RTSemEventMultiSetSignaller on Windows */ 138 } 139 140 141 RTDECL(void) RTSemEventMultiAddSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 142 { 143 } 144 145 146 RTDECL(void) RTSemEventMultiRemoveSignaller(RTSEMEVENTMULTI hEventMultiSem, RTTHREAD hThread) 147 { 148 } 149 -
trunk/src/VBox/Runtime/testcase/tstRTLockValidator.cpp
r25638 r25640 630 630 631 631 632 static DECLCALLBACK(int) test7Thread(RTTHREAD ThreadSelf, void *pvUser) 633 { 634 uintptr_t i = (uintptr_t)pvUser; 635 PRTCRITSECT pMine = &g_aCritSects[i]; 636 PRTCRITSECT pNext = &g_aCritSects[(i + 1) % g_cThreads]; 637 638 RTTEST_CHECK_RC_RET(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS, rcCheck); 639 if (i & 1) 640 RTTEST_CHECK_RC(g_hTest, RTCritSectEnter(pMine), VINF_SUCCESS); 641 if (testWaitForCritSectToBeOwned(pNext)) 642 { 643 int rc; 644 if (i != g_iDeadlockThread) 645 { 646 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectEnter(pNext), VINF_SUCCESS); 647 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 648 if (RT_SUCCESS(rc)) 649 RTTEST_CHECK_RC(g_hTest, rc = RTCritSectLeave(pNext), VINF_SUCCESS); 650 } 651 else 652 { 653 RTTEST_CHECK_RC_OK(g_hTest, rc = testWaitForAllOtherThreadsToSleep(RTTHREADSTATE_CRITSECT, 1)); 654 if (RT_SUCCESS(rc)) 655 { 656 RTSemEventMultiSetSignaller(g_hSemEvtMulti, g_ahThreads[0]); 657 for (uint32_t iThread = 1; iThread < g_cThreads; iThread++) 658 RTSemEventMultiAddSignaller(g_hSemEvtMulti, g_ahThreads[iThread]); 659 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 660 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiReset(g_hSemEvtMulti), VINF_SUCCESS); 661 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VERR_SEM_LV_DEADLOCK); 662 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 663 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiSignal(g_hSemEvtMulti), VINF_SUCCESS); 664 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 665 RTTEST_CHECK_RC(g_hTest, RTSemEventMultiWait(g_hSemEvtMulti, 10*1000), VINF_SUCCESS); 666 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 667 RTSemEventMultiSetSignaller(g_hSemEvtMulti, NIL_RTTHREAD); 668 } 669 } 670 RTTEST_CHECK(g_hTest, RTThreadGetState(RTThreadSelf()) == RTTHREADSTATE_RUNNING); 671 } 672 if (i & 1) 673 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(pMine), VINF_SUCCESS); 674 RTTEST_CHECK_RC(g_hTest, RTCritSectLeave(pMine), VINF_SUCCESS); 675 return VINF_SUCCESS; 676 } 677 678 679 static void test7(uint32_t cThreads, uint32_t cPasses) 680 { 681 testIt(cThreads, cPasses, 0, test7Thread, "event multi"); 682 } 683 632 684 static bool testIsLockValidationCompiledIn(void) 633 685 { … … 669 721 RTTEST_CHECK_RET(g_hTest, RT_FAILURE_NP(rc), false); 670 722 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventDestroy(hSemEvt), false); 723 724 RTSEMEVENTMULTI hSemEvtMulti; 725 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiCreate(&hSemEvtMulti), false); 726 RTSemEventMultiSetSignaller(hSemEvtMulti, RTThreadSelf()); 727 RTSemEventMultiSetSignaller(hSemEvtMulti, NIL_RTTHREAD); 728 rc = RTSemEventMultiSignal(hSemEvtMulti); 729 if (rc != VERR_SEM_LV_NOT_SIGNALLER) 730 fRet = false; 731 RTTEST_CHECK_RET(g_hTest, RT_FAILURE_NP(rc), false); 732 RTTEST_CHECK_RC_OK_RET(g_hTest, RTSemEventMultiDestroy(hSemEvtMulti), false); 671 733 672 734 return fRet; … … 703 765 test6(3, 1); 704 766 #endif 767 test7(3, 1); 705 768 706 769 /* … … 708 771 */ 709 772 RTLockValidatorSetQuiet(true); 773 #if 1 710 774 test1( 2, 256); /* 256 * 4ms = 1s (approx); 4ms == fudge factor */ 711 775 test1( 3, 256); … … 715 779 test1(30, 256); 716 780 717 #if 1718 781 test2( 1, 256); 719 782 test2( 2, 256); … … 738 801 test5(15, 256); 739 802 test5(30, 256); 740 #endif741 803 742 804 test6( 2, 256); … … 746 808 test6(15, 256); 747 809 test6(30, 256); 810 #endif 811 812 #if 1 813 test7( 2, 256); 814 test7( 3, 256); 815 test7( 7, 256); 816 test7(10, 256); 817 test7(15, 256); 818 test7(30, 256); 819 #endif 748 820 749 821 return RTTestSummaryAndDestroy(g_hTest);
Note:
See TracChangeset
for help on using the changeset viewer.