Changeset 92776 in vbox for trunk/src/VBox
- Timestamp:
- Dec 6, 2021 11:56:21 PM (3 years ago)
- Location:
- trunk/src/VBox/Runtime/r3/posix
- Files:
-
- 1 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/posix/semevent-posix.cpp
r82968 r92776 37 37 #include <iprt/mem.h> 38 38 #include <iprt/lockvalidator.h> 39 #include <iprt/time.h> 39 40 40 41 #include "internal/mem.h" … … 54 55 # define pthread_yield() sched_yield() 55 56 #endif 57 58 #include "semwait.h" 56 59 57 60 … … 83 86 /** The creation flags. */ 84 87 uint32_t fFlags; 88 /** Set if we're using the monotonic clock. */ 89 bool fMonotonicClock; 85 90 }; 86 91 … … 121 126 * Create the condition variable. 122 127 */ 123 rc = pthread_cond_init(&pThis->Cond, NULL); 128 pthread_condattr_t CondAttr; 129 rc = pthread_condattr_init(&CondAttr); 124 130 if (!rc) 125 131 { 126 /* 127 * Create the semaphore. 128 */ 129 rc = pthread_mutex_init(&pThis->Mutex, NULL); 132 #if defined(CLOCK_MONOTONIC) && defined(IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK) 133 /* ASSUMES RTTimeSystemNanoTS() == RTTimeNanoTS() == clock_gettime(CLOCK_MONOTONIC). */ 134 rc = pthread_condattr_setclock(&CondAttr, CLOCK_MONOTONIC); 135 pThis->fMonotonicClock = rc == 0; 136 #else 137 pThis->fMonotonicClock = false; 138 #endif 139 rc = pthread_cond_init(&pThis->Cond, &CondAttr); 130 140 if (!rc) 131 141 { 132 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED);133 ASMAtomicWriteU32(&pThis->cWaiters, 0);134 pThis->fFlags = fFlags;135 #ifdef RTSEMEVENT_STRICT 136 if (! pszNameFmt)142 /* 143 * Create the semaphore. 144 */ 145 rc = pthread_mutex_init(&pThis->Mutex, NULL); 146 if (!rc) 137 147 { 138 static uint32_t volatile s_iSemEventAnon = 0; 139 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis, 140 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL), 141 "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1); 148 pthread_condattr_destroy(&CondAttr); 149 150 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED); 151 ASMAtomicWriteU32(&pThis->cWaiters, 0); 152 pThis->fFlags = fFlags; 153 #ifdef RTSEMEVENT_STRICT 154 if (!pszNameFmt) 155 { 156 static uint32_t volatile s_iSemEventAnon = 0; 157 RTLockValidatorRecSharedInit(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis, 158 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL), 159 "RTSemEvent-%u", ASMAtomicIncU32(&s_iSemEventAnon) - 1); 160 } 161 else 162 { 163 va_list va; 164 va_start(va, pszNameFmt); 165 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis, 166 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL), 167 pszNameFmt, va); 168 va_end(va); 169 } 170 pThis->fEverHadSignallers = false; 171 #else 172 RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt); 173 #endif 174 175 *phEventSem = pThis; 176 return VINF_SUCCESS; 142 177 } 143 else 144 { 145 va_list va; 146 va_start(va, pszNameFmt); 147 RTLockValidatorRecSharedInitV(&pThis->Signallers, hClass, RTLOCKVAL_SUB_CLASS_ANY, pThis, 148 true /*fSignaller*/, !(fFlags & RTSEMEVENT_FLAGS_NO_LOCK_VAL), 149 pszNameFmt, va); 150 va_end(va); 151 } 152 pThis->fEverHadSignallers = false; 153 #else 154 RT_NOREF_PV(hClass); RT_NOREF_PV(pszNameFmt); 155 #endif 156 157 *phEventSem = pThis; 158 return VINF_SUCCESS; 178 pthread_cond_destroy(&pThis->Cond); 159 179 } 160 pthread_cond _destroy(&pThis->Cond);180 pthread_condattr_destroy(&CondAttr); 161 181 } 162 182 … … 296 316 297 317 298 DECL_FORCE_INLINE(int) rtSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies, bool fAutoResume) 299 { 300 #ifdef RTSEMEVENT_STRICT 301 PCRTLOCKVALSRCPOS pSrcPos = NULL; 302 #endif 303 318 /** 319 * Handle polling (timeout already expired at the time of the call). 320 * 321 * @returns VINF_SUCCESS, VERR_TIMEOUT, VERR_SEM_DESTROYED. 322 * @param pThis The semaphore. 323 */ 324 DECLINLINE(int) rtSemEventPosixWaitPoll(struct RTSEMEVENTINTERNAL *pThis) 325 { 326 int rc = pthread_mutex_lock(&pThis->Mutex); 327 AssertMsgReturn(!rc, ("Failed to lock event sem %p, rc=%d.\n", pThis, rc), RTErrConvertFromErrno(rc)); 328 329 uint32_t u32OldState; 330 bool fSuccess = ASMAtomicCmpXchgExU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED, EVENT_STATE_SIGNALED, &u32OldState); 331 332 rc = pthread_mutex_unlock(&pThis->Mutex); 333 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc)); NOREF(rc); 334 335 return fSuccess 336 ? VINF_SUCCESS 337 : u32OldState != EVENT_STATE_UNINITIALIZED 338 ? VERR_TIMEOUT 339 : VERR_SEM_DESTROYED; 340 } 341 342 343 /** 344 * Performs an indefinite wait on the event. 345 */ 346 static int rtSemEventPosixWaitIndefinite(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags, PCRTLOCKVALSRCPOS pSrcPos) 347 { 348 RT_NOREF_PV(pSrcPos); 349 350 /* for fairness, yield before going to sleep. */ 351 if ( ASMAtomicIncU32(&pThis->cWaiters) > 1 352 && pThis->u32State == EVENT_STATE_SIGNALED) 353 pthread_yield(); 354 355 /* take mutex */ 356 int rc = pthread_mutex_lock(&pThis->Mutex); 357 if (rc) 358 { 359 ASMAtomicDecU32(&pThis->cWaiters); 360 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", pThis, rc)); 361 return RTErrConvertFromErrno(rc); 362 } 363 364 for (;;) 365 { 366 /* check state. */ 367 if (pThis->u32State == EVENT_STATE_SIGNALED) 368 { 369 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED); 370 ASMAtomicDecU32(&pThis->cWaiters); 371 rc = pthread_mutex_unlock(&pThis->Mutex); 372 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc)); NOREF(rc); 373 return VINF_SUCCESS; 374 } 375 if (pThis->u32State == EVENT_STATE_UNINITIALIZED) 376 { 377 rc = pthread_mutex_unlock(&pThis->Mutex); 378 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc)); NOREF(rc); 379 return VERR_SEM_DESTROYED; 380 } 381 382 /* wait */ 383 #ifdef RTSEMEVENT_STRICT 384 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) 385 ? RTThreadSelfAutoAdopt() 386 : RTThreadSelf(); 387 if (pThis->fEverHadSignallers) 388 { 389 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 390 RT_INDEFINITE_WAIT, RTTHREADSTATE_EVENT, true); 391 if (RT_FAILURE(rc)) 392 { 393 ASMAtomicDecU32(&pThis->cWaiters); 394 pthread_mutex_unlock(&pThis->Mutex); 395 return rc; 396 } 397 } 398 #else 399 RTTHREAD hThreadSelf = RTThreadSelf(); 400 #endif 401 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true); 402 RT_NOREF_PV(fFlags); /** @todo interruptible wait is not implementable... */ 403 rc = pthread_cond_wait(&pThis->Cond, &pThis->Mutex); 404 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT); 405 if (rc) 406 { 407 AssertMsgFailed(("Failed to wait on event sem %p, rc=%d.\n", pThis, rc)); 408 ASMAtomicDecU32(&pThis->cWaiters); 409 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 410 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", pThis, rc2)); NOREF(rc2); 411 return RTErrConvertFromErrno(rc); 412 } 413 } 414 } 415 416 417 /** 418 * Performs an timed wait on the event. 419 */ 420 static int rtSemEventPosixWaitTimed(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags, uint64_t uTimeout, 421 PCRTLOCKVALSRCPOS pSrcPos) 422 { 423 /* 424 * Convert the timeout specification to absolute and relative deadlines, 425 * divierting polling and infinite waits to the appropriate workers. 426 */ 427 struct timespec AbsDeadline = { 0, 0 }; 428 uint64_t const cNsRelativeDeadline = rtSemPosixCalcDeadline(fFlags, uTimeout, pThis->fMonotonicClock, &AbsDeadline); 429 if (cNsRelativeDeadline == 0) 430 return rtSemEventPosixWaitPoll(pThis); 431 if (cNsRelativeDeadline == UINT64_MAX) 432 return rtSemEventPosixWaitIndefinite(pThis, fFlags, pSrcPos); 433 434 /* 435 * Now to the business of waiting... 436 */ 437 438 /* for fairness, yield before going to sleep. */ 439 if (ASMAtomicIncU32(&pThis->cWaiters) > 1) 440 pthread_yield(); 441 442 /* take mutex */ 443 int rc = pthread_mutex_lock(&pThis->Mutex); 444 if (rc) 445 { 446 ASMAtomicDecU32(&pThis->cWaiters); 447 AssertMsg(rc == ETIMEDOUT, ("Failed to lock event sem %p, rc=%d.\n", pThis, rc)); 448 return RTErrConvertFromErrno(rc); 449 } 450 451 for (;;) 452 { 453 /* check state. */ 454 uint32_t const u32State = pThis->u32State; 455 if (u32State != EVENT_STATE_NOT_SIGNALED) 456 { 457 if (u32State == EVENT_STATE_SIGNALED) 458 { 459 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED); 460 ASMAtomicDecU32(&pThis->cWaiters); 461 rc = VINF_SUCCESS; 462 } 463 else 464 { 465 Assert(u32State == EVENT_STATE_UNINITIALIZED); 466 rc = VERR_SEM_DESTROYED; 467 } 468 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 469 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc2=%d.\n", pThis, rc2)); RT_NOREF(rc2); 470 return rc; 471 } 472 473 /* wait */ 474 #ifdef RTSEMEVENT_STRICT 475 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) 476 ? RTThreadSelfAutoAdopt() 477 : RTThreadSelf(); 478 if (pThis->fEverHadSignallers) 479 { 480 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 481 (cNsRelativeDeadline + RT_NS_1MS - 1) / RT_NS_1MS, 482 RTTHREADSTATE_EVENT, true); 483 if (RT_FAILURE(rc)) 484 { 485 ASMAtomicDecU32(&pThis->cWaiters); 486 pthread_mutex_unlock(&pThis->Mutex); 487 return rc; 488 } 489 } 490 #else 491 RTTHREAD hThreadSelf = RTThreadSelf(); 492 #endif 493 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true); 494 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &AbsDeadline); 495 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT); 496 497 /* According to SuS this function shall not return EINTR, but linux man page might have said differently at some point... */ 498 if ( rc != 0 499 && ( rc != EINTR 500 || !(fFlags & RTSEMWAIT_FLAGS_NORESUME))) 501 { 502 AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event sem %p, rc=%d.\n", pThis, rc)); 503 ASMAtomicDecU32(&pThis->cWaiters); 504 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 505 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc2=%d.\n", pThis, rc2)); NOREF(rc2); 506 return RTErrConvertFromErrno(rc); 507 } 508 } /* for (;;) */ 509 } 510 511 512 /** 513 * Internal wait worker function. 514 */ 515 DECLINLINE(int) rtSemEventPosixWait(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos) 516 { 304 517 /* 305 518 * Validate input. … … 309 522 uint32_t u32 = pThis->u32State; 310 523 AssertReturn(u32 == EVENT_STATE_NOT_SIGNALED || u32 == EVENT_STATE_SIGNALED, VERR_INVALID_HANDLE); 524 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); 311 525 312 526 /* 313 527 * Timed or indefinite wait? 314 528 */ 529 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE) 530 return rtSemEventPosixWaitIndefinite(pThis, fFlags, pSrcPos); 531 return rtSemEventPosixWaitTimed(hEventSem, fFlags, uTimeout, pSrcPos); 532 } 533 534 535 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 536 { 537 int rc; 538 #ifndef RTSEMEVENT_STRICT 315 539 if (cMillies == RT_INDEFINITE_WAIT) 316 { 317 /* for fairness, yield before going to sleep. */ 318 if ( ASMAtomicIncU32(&pThis->cWaiters) > 1 319 && pThis->u32State == EVENT_STATE_SIGNALED) 320 pthread_yield(); 321 322 /* take mutex */ 323 int rc = pthread_mutex_lock(&pThis->Mutex); 324 if (rc) 325 { 326 ASMAtomicDecU32(&pThis->cWaiters); 327 AssertMsgFailed(("Failed to lock event sem %p, rc=%d.\n", hEventSem, rc)); 328 return RTErrConvertFromErrno(rc); 329 } 330 331 for (;;) 332 { 333 /* check state. */ 334 if (pThis->u32State == EVENT_STATE_SIGNALED) 335 { 336 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED); 337 ASMAtomicDecU32(&pThis->cWaiters); 338 rc = pthread_mutex_unlock(&pThis->Mutex); 339 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", hEventSem, rc)); NOREF(rc); 340 return VINF_SUCCESS; 341 } 342 if (pThis->u32State == EVENT_STATE_UNINITIALIZED) 343 { 344 rc = pthread_mutex_unlock(&pThis->Mutex); 345 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", hEventSem, rc)); NOREF(rc); 346 return VERR_SEM_DESTROYED; 347 } 348 349 /* wait */ 350 #ifdef RTSEMEVENT_STRICT 351 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) 352 ? RTThreadSelfAutoAdopt() 353 : RTThreadSelf(); 354 if (pThis->fEverHadSignallers) 355 { 356 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 357 cMillies, RTTHREADSTATE_EVENT, true); 358 if (RT_FAILURE(rc)) 359 { 360 ASMAtomicDecU32(&pThis->cWaiters); 361 pthread_mutex_unlock(&pThis->Mutex); 362 return rc; 363 } 364 } 365 #else 366 RTTHREAD hThreadSelf = RTThreadSelf(); 367 #endif 368 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true); 369 rc = pthread_cond_wait(&pThis->Cond, &pThis->Mutex); 370 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT); 371 if (rc) 372 { 373 AssertMsgFailed(("Failed to wait on event sem %p, rc=%d.\n", hEventSem, rc)); 374 ASMAtomicDecU32(&pThis->cWaiters); 375 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 376 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc=%d.\n", hEventSem, rc2)); NOREF(rc2); 377 return RTErrConvertFromErrno(rc); 378 } 379 } 380 } 381 else 382 { 383 /* 384 * Get current time and calc end of wait time. 385 */ 386 struct timespec ts = {0,0}; 387 #if defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU) 388 struct timeval tv = {0,0}; 389 gettimeofday(&tv, NULL); 390 ts.tv_sec = tv.tv_sec; 391 ts.tv_nsec = tv.tv_usec * 1000; 392 #else 393 clock_gettime(CLOCK_REALTIME, &ts); 394 #endif 395 if (cMillies != 0) 396 { 397 ts.tv_nsec += (cMillies % 1000) * 1000000; 398 ts.tv_sec += cMillies / 1000; 399 if (ts.tv_nsec >= 1000000000) 400 { 401 ts.tv_nsec -= 1000000000; 402 ts.tv_sec++; 403 } 404 } 405 406 /* for fairness, yield before going to sleep. */ 407 if (ASMAtomicIncU32(&pThis->cWaiters) > 1 && cMillies) 408 pthread_yield(); 409 410 /* take mutex */ 411 int rc = pthread_mutex_lock(&pThis->Mutex); 412 if (rc) 413 { 414 ASMAtomicDecU32(&pThis->cWaiters); 415 AssertMsg(rc == ETIMEDOUT, ("Failed to lock event sem %p, rc=%d.\n", hEventSem, rc)); 416 return RTErrConvertFromErrno(rc); 417 } 418 419 for (;;) 420 { 421 /* check state. */ 422 if (pThis->u32State == EVENT_STATE_SIGNALED) 423 { 424 ASMAtomicWriteU32(&pThis->u32State, EVENT_STATE_NOT_SIGNALED); 425 ASMAtomicDecU32(&pThis->cWaiters); 426 rc = pthread_mutex_unlock(&pThis->Mutex); 427 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", hEventSem, rc)); NOREF(rc); 428 return VINF_SUCCESS; 429 } 430 if (pThis->u32State == EVENT_STATE_UNINITIALIZED) 431 { 432 rc = pthread_mutex_unlock(&pThis->Mutex); 433 AssertMsg(!rc, ("Failed to unlock event sem %p, rc=%d.\n", hEventSem, rc)); NOREF(rc); 434 return VERR_SEM_DESTROYED; 435 } 436 437 /* we're done if the timeout is 0. */ 438 if (!cMillies) 439 { 440 ASMAtomicDecU32(&pThis->cWaiters); 441 rc = pthread_mutex_unlock(&pThis->Mutex); 442 return VERR_TIMEOUT; 443 } 444 445 /* wait */ 446 #ifdef RTSEMEVENT_STRICT 447 RTTHREAD hThreadSelf = !(pThis->fFlags & RTSEMEVENT_FLAGS_BOOTSTRAP_HACK) 448 ? RTThreadSelfAutoAdopt() 449 : RTThreadSelf(); 450 if (pThis->fEverHadSignallers) 451 { 452 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 453 cMillies, RTTHREADSTATE_EVENT, true); 454 if (RT_FAILURE(rc)) 455 { 456 ASMAtomicDecU32(&pThis->cWaiters); 457 pthread_mutex_unlock(&pThis->Mutex); 458 return rc; 459 } 460 } 461 #else 462 RTTHREAD hThreadSelf = RTThreadSelf(); 463 #endif 464 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT, true); 465 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &ts); 466 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT); 467 if (rc && (rc != EINTR || !fAutoResume)) /* according to SuS this function shall not return EINTR, but linux man page says differently. */ 468 { 469 AssertMsg(rc == ETIMEDOUT, ("Failed to wait on event sem %p, rc=%d.\n", hEventSem, rc)); 470 ASMAtomicDecU32(&pThis->cWaiters); 471 int rc2 = pthread_mutex_unlock(&pThis->Mutex); 472 AssertMsg(!rc2, ("Failed to unlock event sem %p, rc2=%d.\n", hEventSem, rc2)); NOREF(rc2); 473 return RTErrConvertFromErrno(rc); 474 } 475 } /* for (;;) */ 476 } 477 } 478 479 480 RTDECL(int) RTSemEventWait(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 481 { 482 int rc = rtSemEventWait(hEventSem, cMillies, true); 540 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL); 541 else 542 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS, 543 cMillies, NULL); 544 #else 545 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); 546 if (cMillies == RT_INDEFINITE_WAIT) 547 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos); 548 else 549 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_RESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS, 550 cMillies, &SrcPos); 551 #endif 483 552 Assert(rc != VERR_INTERRUPTED); 484 553 return rc; … … 488 557 RTDECL(int) RTSemEventWaitNoResume(RTSEMEVENT hEventSem, RTMSINTERVAL cMillies) 489 558 { 490 return rtSemEventWait(hEventSem, cMillies, false); 559 int rc; 560 #ifndef RTSEMEVENT_STRICT 561 if (cMillies == RT_INDEFINITE_WAIT) 562 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, NULL); 563 else 564 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS, 565 cMillies, NULL); 566 #else 567 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); 568 if (cMillies == RT_INDEFINITE_WAIT) 569 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_INDEFINITE, 0, &SrcPos); 570 else 571 rc = rtSemEventPosixWait(hEventSem, RTSEMWAIT_FLAGS_NORESUME | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_MILLISECS, 572 cMillies, &SrcPos); 573 #endif 574 Assert(rc != VERR_INTERRUPTED); 575 return rc; 576 } 577 578 579 RTDECL(int) RTSemEventWaitEx(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout) 580 { 581 #ifndef RTSEMEVENT_STRICT 582 return rtSemEventPosixWait(hEventSem, fFlags, uTimeout, NULL); 583 #else 584 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_NORMAL_API(); 585 return rtSemEventPosixWait(hEventSem, fFlags, uTimeout, &SrcPos); 586 #endif 587 } 588 589 590 RTDECL(int) RTSemEventWaitExDebug(RTSEMEVENT hEventSem, uint32_t fFlags, uint64_t uTimeout, 591 RTHCUINTPTR uId, RT_SRC_POS_DECL) 592 { 593 RTLOCKVALSRCPOS SrcPos = RTLOCKVALSRCPOS_INIT_DEBUG_API(); 594 return rtSemEventPosixWait(hEventSem, fFlags, uTimeout, &SrcPos); 595 } 596 597 598 RTDECL(uint32_t) RTSemEventGetResolution(void) 599 { 600 /** @todo we have 1ns parameter resolution, but we need to check each host 601 * what the actual resolution might be once the parameter makes it to the 602 * kernel and is processed there. */ 603 return 1; 491 604 } 492 605 -
trunk/src/VBox/Runtime/r3/posix/semeventmulti-posix.cpp
r88294 r92776 46 46 #include <sys/time.h> 47 47 48 49 /********************************************************************************************************************************* 50 * Defined Constants And Macros * 51 *********************************************************************************************************************************/ 52 /** @def IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK 53 * Set if the platform implements pthread_condattr_setclock(). 54 * Enables the use of the monotonic clock for waiting on condition variables. */ 55 #ifndef IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK 56 /* Linux detection */ 57 # if defined(RT_OS_LINUX) && defined(__USE_XOPEN2K) 58 # include <features.h> 59 # if __GLIBC_PREREQ(2,6) /** @todo figure the exact version where this was added */ 60 # define IPRT_HAVE_PTHREAD_CONDATTR_SETCLOCK 61 # endif 62 # endif 63 /** @todo check other platforms */ 64 #endif 48 #include "semwait.h" 65 49 66 50 … … 147 131 pthread_condattr_destroy(&CondAttr); 148 132 149 ASMAtomic XchgU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED);150 ASMAtomic XchgU32(&pThis->cWaiters, 0);133 ASMAtomicWriteU32(&pThis->u32State, EVENTMULTI_STATE_NOT_SIGNALED); 134 ASMAtomicWriteU32(&pThis->cWaiters, 0); 151 135 #ifdef RTSEMEVENTMULTI_STRICT 152 136 if (!pszNameFmt) … … 179 163 pthread_condattr_destroy(&CondAttr); 180 164 } 181 182 165 rc = RTErrConvertFromErrno(rc); 183 166 RTMemFree(pThis); … … 454 437 { 455 438 /* 456 * Convert uTimeout to a relative value in nano seconds. 457 */ 458 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 459 uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) 460 ? uTimeout * UINT32_C(1000000) 461 : UINT64_MAX; 462 if (uTimeout == UINT64_MAX) /* unofficial way of indicating an indefinite wait */ 439 * Convert the timeout specification to absolute and relative deadlines, 440 * divierting polling and infinite waits to the appropriate workers. 441 */ 442 struct timespec AbsDeadline = { 0, 0 }; 443 uint64_t const cNsRelativeDeadline = rtSemPosixCalcDeadline(fFlags, uTimeout, pThis->fMonotonicClock, &AbsDeadline); 444 if (cNsRelativeDeadline == 0) 445 return rtSemEventMultiPosixWaitPoll(pThis); 446 if (cNsRelativeDeadline == UINT64_MAX) 463 447 return rtSemEventMultiPosixWaitIndefinite(pThis, fFlags, pSrcPos); 464 465 uint64_t uAbsTimeout = uTimeout;466 if (fFlags & RTSEMWAIT_FLAGS_ABSOLUTE)467 {468 uint64_t u64Now = RTTimeSystemNanoTS();469 uTimeout = uTimeout > u64Now ? uTimeout - u64Now : 0;470 }471 472 if (uTimeout == 0)473 return rtSemEventMultiPosixWaitPoll(pThis);474 475 /*476 * Get current time and calc end of deadline relative to real time.477 */478 struct timespec ts = {0,0};479 if (!pThis->fMonotonicClock)480 {481 #if defined(RT_OS_DARWIN) || defined(RT_OS_HAIKU)482 struct timeval tv = {0,0};483 gettimeofday(&tv, NULL);484 ts.tv_sec = tv.tv_sec;485 ts.tv_nsec = tv.tv_usec * 1000;486 #else487 clock_gettime(CLOCK_REALTIME, &ts);488 #endif489 struct timespec tsAdd;490 tsAdd.tv_nsec = uTimeout % UINT32_C(1000000000);491 tsAdd.tv_sec = uTimeout / UINT32_C(1000000000);492 if ( sizeof(ts.tv_sec) < sizeof(uint64_t)493 && ( uTimeout > UINT64_C(1000000000) * UINT32_MAX494 || (uint64_t)ts.tv_sec + tsAdd.tv_sec >= UINT32_MAX) )495 return rtSemEventMultiPosixWaitIndefinite(pThis, fFlags, pSrcPos);496 497 ts.tv_sec += tsAdd.tv_sec;498 ts.tv_nsec += tsAdd.tv_nsec;499 if (ts.tv_nsec >= 1000000000)500 {501 ts.tv_nsec -= 1000000000;502 ts.tv_sec++;503 }504 /* Note! No need to complete uAbsTimeout for RTSEMWAIT_FLAGS_RELATIVE in this path. */505 }506 else507 {508 /* ASSUMES RTTimeSystemNanoTS() == RTTimeNanoTS() == clock_gettime(CLOCK_MONOTONIC). */509 if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)510 uAbsTimeout += RTTimeSystemNanoTS();511 if ( sizeof(ts.tv_sec) < sizeof(uint64_t)512 && uAbsTimeout > UINT64_C(1000000000) * UINT32_MAX)513 return rtSemEventMultiPosixWaitIndefinite(pThis, fFlags, pSrcPos);514 ts.tv_nsec = uAbsTimeout % UINT32_C(1000000000);515 ts.tv_sec = uAbsTimeout / UINT32_C(1000000000);516 }517 448 518 449 /* … … 544 475 { 545 476 rc = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 546 uTimeout / UINT32_C(1000000), RTTHREADSTATE_EVENT_MULTI, true);477 (uTimeout + RT_NS_1MS - 1)/ RT_NS_1MS, RTTHREADSTATE_EVENT_MULTI, true); 547 478 if (RT_FAILURE(rc)) 548 479 { … … 556 487 #endif 557 488 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true); 558 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, & ts);489 rc = pthread_cond_timedwait(&pThis->Cond, &pThis->Mutex, &AbsDeadline); 559 490 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI); 560 if ( rc 561 && ( rc != EINTR /* according to SuS this function shall not return EINTR, but linux man page says differently. */ 491 492 /* According to SuS this function shall not return EINTR, but linux man page might have said differently at some point... */ 493 if ( rc != 0 494 && ( rc != EINTR 562 495 || (fFlags & RTSEMWAIT_FLAGS_NORESUME)) ) 563 496 { … … 568 501 return RTErrConvertFromErrno(rc); 569 502 } 570 571 /* check the absolute deadline. */572 503 } 573 504 }
Note:
See TracChangeset
for help on using the changeset viewer.