Changeset 92782 in vbox for trunk/src/VBox/Runtime/r3/linux
- Timestamp:
- Dec 7, 2021 10:58:17 AM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 148700
- Location:
- trunk/src/VBox/Runtime/r3/linux
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r3/linux/semevent-linux.cpp
r92779 r92782 134 134 if (pThis) 135 135 { 136 pThis->iMagic = RTSEMEVENT_MAGIC;137 pThis->cWaiters = 0;136 pThis->iMagic = RTSEMEVENT_MAGIC; 137 pThis->cWaiters = 0; 138 138 pThis->fSignalled = 0; 139 pThis->fFlags = fFlags;139 pThis->fFlags = fFlags; 140 140 #ifdef RTSEMEVENT_STRICT 141 141 if (!pszNameFmt) … … 318 318 319 319 320 /** 321 * Handle polling (timeout already expired at the time of the call). 322 * 323 * @returns VINF_SUCCESS, VERR_TIMEOUT, VERR_SEM_DESTROYED. 324 * @param pThis The semaphore. 325 */ 320 326 static int rtSemEventLinuxWaitPoll(struct RTSEMEVENTINTERNAL *pThis) 321 327 { … … 332 338 333 339 340 /** 341 * Performs an timed wait on the event. 342 */ 334 343 static int rtSemEventLinuxWaitTimed(struct RTSEMEVENTINTERNAL *pThis, uint32_t fFlags, 335 344 uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos) … … 340 349 * Convert the timeout value. 341 350 */ 342 int iWaitOp; 343 uint32_t uWaitVal3; 344 timespec TsTimeout; 345 uint64_t uAbsTimeout = uTimeout; /* Note! only relevant for relative waits (FUTEX_WAIT). */ 346 if (fFlags & RTSEMWAIT_FLAGS_RELATIVE) 347 { 348 if (!uTimeout) 349 return rtSemEventLinuxWaitPoll(pThis); 350 351 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 352 { 353 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t) 354 || uTimeout < (uint64_t)UINT32_MAX * RT_MS_1SEC) 355 { 356 TsTimeout.tv_sec = uTimeout / RT_MS_1SEC; 357 TsTimeout.tv_nsec = (uTimeout % RT_MS_1SEC) & RT_NS_1MS; 358 uAbsTimeout *= RT_NS_1MS; 359 } 360 else 361 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 362 } 363 else 364 { 365 Assert(fFlags & RTSEMWAIT_FLAGS_NANOSECS); 366 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t) 367 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC) 368 { 369 TsTimeout.tv_sec = uTimeout / RT_NS_1SEC; 370 TsTimeout.tv_nsec = uTimeout % RT_NS_1SEC; 371 } 372 else 373 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 374 } 375 376 if (fFlags & RTSEMWAIT_FLAGS_RESUME) 377 uAbsTimeout += RTTimeNanoTS(); 378 379 iWaitOp = FUTEX_WAIT; 380 uWaitVal3 = 0; 381 } 382 else 383 { 384 /* Absolute deadline: */ 385 Assert(fFlags & RTSEMWAIT_FLAGS_ABSOLUTE); 386 if (g_fCanUseWaitBitSet == true) 387 { 388 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 389 { 390 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t) 391 || uTimeout < (uint64_t)UINT32_MAX * RT_MS_1SEC) 392 { 393 TsTimeout.tv_sec = uTimeout / RT_MS_1SEC; 394 TsTimeout.tv_nsec = (uTimeout % RT_MS_1SEC) & RT_NS_1MS; 395 } 396 else 397 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 398 } 399 else 400 { 401 Assert(fFlags & RTSEMWAIT_FLAGS_NANOSECS); 402 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t) 403 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC) 404 { 405 TsTimeout.tv_sec = uTimeout / RT_NS_1SEC; 406 TsTimeout.tv_nsec = uTimeout % RT_NS_1SEC; 407 } 408 else 409 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 410 } 411 iWaitOp = FUTEX_WAIT_BITSET; 412 uWaitVal3 = UINT32_MAX; 413 } 414 else 415 { 416 /* Recalculate it as an relative timeout: */ 417 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 418 { 419 if (uTimeout < UINT64_MAX / RT_NS_1MS) 420 uAbsTimeout = uTimeout *= RT_NS_1MS; 421 else 422 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 423 } 424 425 uint64_t const u64Now = RTTimeNanoTS(); 426 if (u64Now < uTimeout) 427 uTimeout -= u64Now; 428 else 429 return rtSemEventLinuxWaitPoll(pThis); 430 431 if ( sizeof(TsTimeout.tv_sec) >= sizeof(uint64_t) 432 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC) 433 { 434 TsTimeout.tv_sec = uTimeout / RT_NS_1SEC; 435 TsTimeout.tv_nsec = uTimeout % RT_NS_1SEC; 436 } 437 else 438 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 439 440 iWaitOp = FUTEX_WAIT; 441 uWaitVal3 = 0; 442 } 443 } 351 struct timespec TsTimeout; 352 int iWaitOp; 353 uint32_t uWaitVal3; 354 uint64_t nsAbsTimeout; 355 uTimeout = rtSemLinuxCalcDeadline(fFlags, uTimeout, g_fCanUseWaitBitSet, &TsTimeout, &iWaitOp, &uWaitVal3, &nsAbsTimeout); 356 if (uTimeout == 0) 357 return rtSemEventLinuxWaitPoll(pThis); 358 if (uTimeout == UINT64_MAX) 359 return rtSemEventLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 444 360 445 361 /* … … 494 410 else if (lrc == -ETIMEDOUT) 495 411 { 412 #ifdef RT_STRICT 413 uint64_t const uNow = RTTimeNanoTS(); 414 AssertMsg(uNow >= nsAbsTimeout || nsAbsTimeout - uNow < RT_NS_1MS, 415 ("%#RX64 - %#RX64 => %#RX64 (%RI64)\n", nsAbsTimeout, uNow, nsAbsTimeout - uNow, nsAbsTimeout - uNow)); 416 #endif 496 417 rc = VERR_TIMEOUT; 497 418 break; … … 516 437 if (iWaitOp == FUTEX_WAIT) 517 438 { 518 int64_t i64Diff = uAbsTimeout - RTTimeSystemNanoTS();439 int64_t i64Diff = nsAbsTimeout - RTTimeSystemNanoTS(); 519 440 if (i64Diff < 1000) 520 441 { … … 542 463 struct RTSEMEVENTINTERNAL *pThis = hEventSem; 543 464 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 544 uint32_t fSignalled = pThis->fSignalled; 545 AssertReturn(fSignalled == false || fSignalled == true, VERR_INVALID_HANDLE); 465 AssertReturn(pThis->iMagic == RTSEMEVENT_MAGIC, VERR_INVALID_HANDLE); 546 466 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); 467 #ifdef RT_STRICT 468 uint32_t const fSignalled = pThis->fSignalled; 469 Assert(fSignalled == false || fSignalled == true); 470 #endif 547 471 548 472 /* -
trunk/src/VBox/Runtime/r3/linux/semeventmulti-linux.cpp
r92779 r92782 268 268 269 269 270 271 DECLINLINE(int) rtSemEventLnxMultiWait(struct RTSEMEVENTMULTIINTERNAL *pThis, uint32_t fFlags, uint64_t uTimeout, 272 PCRTLOCKVALSRCPOS pSrcPos) 270 /** 271 * Performs an indefinite wait on the event. 272 */ 273 static int rtSemEventMultiLinuxWaitIndefinite(struct RTSEMEVENTMULTIINTERNAL *pThis, uint32_t fFlags, PCRTLOCKVALSRCPOS pSrcPos) 273 274 { 274 275 RT_NOREF(pSrcPos); 275 276 /*277 * Validate input.278 */279 AssertPtrReturn(pThis, VERR_INVALID_HANDLE);280 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE);281 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER);282 276 283 277 /* … … 288 282 return VINF_SUCCESS; 289 283 ASSERT_VALID_STATE(uState); 290 291 /*292 * Check and convert the timeout value.293 */294 struct timespec ts;295 struct timespec *pTimeout = NULL;296 uint64_t u64Deadline = 0; /* shut up gcc */297 if (!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE))298 {299 /* If the timeout is zero, then we're done. */300 if (!uTimeout)301 return VERR_TIMEOUT;302 303 /* Convert it to a deadline + interval timespec. */304 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS)305 uTimeout = uTimeout < UINT64_MAX / UINT32_C(1000000) * UINT32_C(1000000)306 ? uTimeout * UINT32_C(1000000)307 : UINT64_MAX;308 if (uTimeout != UINT64_MAX) /* unofficial way of indicating an indefinite wait */309 {310 if (fFlags & RTSEMWAIT_FLAGS_RELATIVE)311 u64Deadline = RTTimeSystemNanoTS() + uTimeout;312 else313 {314 uint64_t u64Now = RTTimeSystemNanoTS();315 if (uTimeout <= u64Now)316 return VERR_TIMEOUT;317 u64Deadline = uTimeout;318 uTimeout -= u64Now;319 }320 if ( sizeof(ts.tv_sec) >= sizeof(uint64_t)321 || uTimeout <= UINT64_C(1000000000) * UINT32_MAX)322 {323 ts.tv_nsec = uTimeout % UINT32_C(1000000000);324 ts.tv_sec = uTimeout / UINT32_C(1000000000);325 pTimeout = &ts;326 }327 }328 }329 284 330 285 /* … … 348 303 RTSEMEVENTMULTI_LNX_NOT_SIGNALED))) 349 304 { 350 /* adjust the relative timeout */351 if (pTimeout)352 {353 int64_t i64Diff = u64Deadline - RTTimeSystemNanoTS();354 if (i64Diff < 1000)355 return VERR_TIMEOUT;356 ts.tv_sec = (uint64_t)i64Diff / UINT32_C(1000000000);357 ts.tv_nsec = (uint64_t)i64Diff % UINT32_C(1000000000);358 }359 305 #ifdef RTSEMEVENTMULTI_STRICT 360 306 if (pThis->fEverHadSignallers) 361 307 { 362 308 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 363 uTimeout / UINT32_C(1000000), RTTHREADSTATE_EVENT_MULTI, true);309 RT_INDEFINITE_WAIT, RTTHREADSTATE_EVENT_MULTI, true); 364 310 if (RT_FAILURE(rc9)) 365 311 return rc9; … … 370 316 #endif 371 317 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true); 372 long rc = sys_futex(&pThis->uState, FUTEX_WAIT, 1, pTimeout, NULL, 0);318 long rc = sys_futex(&pThis->uState, FUTEX_WAIT, 1, NULL /*pTimeout*/, NULL, 0); 373 319 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI); 374 if (RT_UNLIKELY(pThis->u32Magic != RTSEMEVENTMULTI_MAGIC)) 320 321 /* Check that the structure is still alive before continuing. */ 322 if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC)) 323 { /*likely*/ } 324 else 375 325 return VERR_SEM_DESTROYED; 326 327 /* 328 * Return if success. 329 */ 376 330 if (rc == 0) 377 331 { … … 383 337 * Act on the wakup code. 384 338 */ 385 if (rc == -ETIMEDOUT)386 {387 /** @todo something is broken here. shows up every now and again in the ata388 * code. Should try to run the timeout against RTTimeMilliTS to389 * check that it's doing the right thing... */390 Assert(pTimeout);391 return VERR_TIMEOUT;392 }393 339 if (rc == -EWOULDBLOCK) 394 340 /* retry, the value changed. */; … … 413 359 414 360 361 /** 362 * Handle polling (timeout already expired at the time of the call). 363 * 364 * @returns VINF_SUCCESS, VERR_TIMEOUT, VERR_SEM_DESTROYED. 365 * @param pThis The semaphore. 366 */ 367 static int rtSemEventMultiLinuxWaitPoll(struct RTSEMEVENTMULTIINTERNAL *pThis) 368 { 369 uint32_t uState = ASMAtomicUoReadU32(&pThis->uState); 370 if (uState == RTSEMEVENTMULTI_LNX_SIGNALED) 371 return VINF_SUCCESS; 372 return VERR_TIMEOUT; 373 } 374 375 376 /** 377 * Performs an indefinite wait on the event. 378 */ 379 static int rtSemEventMultiLinuxWaitTimed(struct RTSEMEVENTMULTIINTERNAL *pThis, uint32_t fFlags, uint64_t uTimeout, 380 PCRTLOCKVALSRCPOS pSrcPos) 381 { 382 RT_NOREF(pSrcPos); 383 384 /* 385 * Quickly check whether it's signaled. 386 */ 387 uint32_t uState = ASMAtomicUoReadU32(&pThis->uState); 388 if (uState == RTSEMEVENTMULTI_LNX_SIGNALED) 389 return VINF_SUCCESS; 390 ASSERT_VALID_STATE(uState); 391 392 /* 393 * Convert the timeout value. 394 */ 395 struct timespec TsTimeout; 396 int iWaitOp; 397 uint32_t uWaitVal3; 398 uint64_t nsAbsTimeout; 399 uTimeout = rtSemLinuxCalcDeadline(fFlags, uTimeout, g_fCanUseWaitBitSet, &TsTimeout, &iWaitOp, &uWaitVal3, &nsAbsTimeout); 400 if (uTimeout == 0) 401 return rtSemEventMultiLinuxWaitPoll(pThis); 402 if (uTimeout == UINT64_MAX) 403 return rtSemEventMultiLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 404 405 /* 406 * The wait loop. 407 */ 408 #ifdef RTSEMEVENTMULTI_STRICT 409 RTTHREAD hThreadSelf = RTThreadSelfAutoAdopt(); 410 #else 411 RTTHREAD hThreadSelf = RTThreadSelf(); 412 #endif 413 for (unsigned i = 0;; i++) 414 { 415 /* 416 * Start waiting. We only account for there being or having been 417 * threads waiting on the semaphore to keep things simple. 418 */ 419 uState = ASMAtomicUoReadU32(&pThis->uState); 420 if ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS 421 || ( uState == RTSEMEVENTMULTI_LNX_NOT_SIGNALED 422 && ASMAtomicCmpXchgU32(&pThis->uState, RTSEMEVENTMULTI_LNX_NOT_SIGNALED_WAITERS, 423 RTSEMEVENTMULTI_LNX_NOT_SIGNALED))) 424 { 425 #ifdef RTSEMEVENTMULTI_STRICT 426 if (pThis->fEverHadSignallers) 427 { 428 int rc9 = RTLockValidatorRecSharedCheckBlocking(&pThis->Signallers, hThreadSelf, pSrcPos, false, 429 uTimeout / UINT32_C(1000000), RTTHREADSTATE_EVENT_MULTI, true); 430 if (RT_FAILURE(rc9)) 431 return rc9; 432 } 433 #endif 434 #ifdef RT_STRICT 435 uint32_t const uPrevSignalSerialNo = ASMAtomicReadU32(&pThis->uSignalSerialNo); 436 #endif 437 RTThreadBlocking(hThreadSelf, RTTHREADSTATE_EVENT_MULTI, true); 438 long rc = sys_futex(&pThis->uState, iWaitOp, 1, &TsTimeout, NULL, uWaitVal3); 439 RTThreadUnblocked(hThreadSelf, RTTHREADSTATE_EVENT_MULTI); 440 441 /* Check that the structure is still alive before continuing. */ 442 if (RT_LIKELY(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC)) 443 { /*likely*/ } 444 else 445 return VERR_SEM_DESTROYED; 446 447 /* 448 * Return if success. 449 */ 450 if (rc == 0) 451 { 452 Assert(uPrevSignalSerialNo != ASMAtomicReadU32(&pThis->uSignalSerialNo)); 453 return VINF_SUCCESS; 454 } 455 456 /* 457 * Act on the wakup code. 458 */ 459 if (rc == -ETIMEDOUT) 460 { 461 /** @todo something is broken here. shows up every now and again in the ata 462 * code. Should try to run the timeout against RTTimeMilliTS to 463 * check that it's doing the right thing... */ 464 #ifdef RT_STRICT 465 uint64_t const uNow = RTTimeNanoTS(); 466 AssertMsg(uNow >= nsAbsTimeout || nsAbsTimeout - uNow < RT_NS_1MS, 467 ("%#RX64 - %#RX64 => %#RX64 (%RI64)\n", nsAbsTimeout, uNow, nsAbsTimeout - uNow, nsAbsTimeout - uNow)); 468 #endif 469 return VERR_TIMEOUT; 470 } 471 if (rc == -EWOULDBLOCK) 472 { 473 /* retry, the value changed. */; 474 } 475 else if (rc == -EINTR) 476 { 477 if (fFlags & RTSEMWAIT_FLAGS_NORESUME) 478 return VERR_INTERRUPTED; 479 } 480 else 481 { 482 /* this shouldn't happen! */ 483 AssertMsgFailed(("rc=%ld errno=%d\n", rc, errno)); 484 return RTErrConvertFromErrno(rc); 485 } 486 } 487 else if (uState == RTSEMEVENTMULTI_LNX_SIGNALED) 488 return VINF_SUCCESS; 489 else 490 ASSERT_VALID_STATE(uState); 491 492 /* adjust the relative timeout if relative */ 493 if (iWaitOp == FUTEX_WAIT) 494 { 495 int64_t i64Diff = nsAbsTimeout - RTTimeSystemNanoTS(); 496 if (i64Diff < 1000) 497 return VERR_TIMEOUT; 498 TsTimeout.tv_sec = (uint64_t)i64Diff / RT_NS_1SEC; 499 TsTimeout.tv_nsec = (uint64_t)i64Diff % RT_NS_1SEC; 500 } 501 } 502 } 503 504 /** 505 * Internal wait worker function. 506 */ 507 DECLINLINE(int) rtSemEventLnxMultiWait(RTSEMEVENTMULTI hEventSem, uint32_t fFlags, uint64_t uTimeout, PCRTLOCKVALSRCPOS pSrcPos) 508 { 509 /* 510 * Validate input. 511 */ 512 struct RTSEMEVENTMULTIINTERNAL *pThis = hEventSem; 513 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 514 AssertReturn(pThis->u32Magic == RTSEMEVENTMULTI_MAGIC, VERR_INVALID_HANDLE); 515 AssertReturn(RTSEMWAIT_FLAGS_ARE_VALID(fFlags), VERR_INVALID_PARAMETER); 516 517 /* 518 * Timed or indefinite wait? 519 */ 520 if (fFlags & RTSEMWAIT_FLAGS_INDEFINITE) 521 return rtSemEventMultiLinuxWaitIndefinite(pThis, fFlags, pSrcPos); 522 return rtSemEventMultiLinuxWaitTimed(hEventSem, fFlags, uTimeout, pSrcPos); 523 } 524 525 415 526 #undef RTSemEventMultiWaitEx 416 527 RTDECL(int) RTSemEventMultiWaitEx(RTSEMEVENTMULTI hEventMultiSem, uint32_t fFlags, uint64_t uTimeout) -
trunk/src/VBox/Runtime/r3/linux/semwait-linux.h
r92779 r92782 71 71 } 72 72 73 74 /** 75 * Converts a extended wait timeout specification to an timespec and 76 * corresponding futex operation, as well as an approximate relative nanosecond 77 * interval. 78 * 79 * @note This does not check for RTSEMWAIT_FLAGS_INDEFINITE, caller should've 80 * done that already. 81 * 82 * @returns The relative wait in nanoseconds. 0 for a poll call, UINT64_MAX for 83 * an effectively indefinite wait. 84 * @param fFlags RTSEMWAIT_FLAGS_XXX. 85 * @param fCanUseWaitBitSet Whether we can use FUTEX_WAIT_BITMSET or not. 86 * @param uTimeout The timeout. 87 * @param pDeadline Where to return the deadline. 88 * @param piWaitOp Where to return the FUTEX wait operation number. 89 * @param puWaitVal3 Where to return the FUTEX wait value 3. 90 * @param pnsAbsTimeout Where to return the absolute timeout in case of 91 * a resuming relative call (i.e. FUTEX_WAIT). 92 */ 93 DECL_FORCE_INLINE(uint64_t) 94 rtSemLinuxCalcDeadline(uint32_t fFlags, uint64_t uTimeout, int fCanUseWaitBitSet, 95 struct timespec *pDeadline, int *piWaitOp, uint32_t *puWaitVal3, uint64_t *pnsAbsTimeout) 96 { 97 Assert(!(fFlags & RTSEMWAIT_FLAGS_INDEFINITE)); 98 99 if (fFlags & RTSEMWAIT_FLAGS_RELATIVE) 100 { 101 Assert(!(fFlags & RTSEMWAIT_FLAGS_ABSOLUTE)); 102 103 /* 104 * Polling call? 105 */ 106 if (uTimeout == 0) 107 return 0; 108 109 /* 110 * We use FUTEX_WAIT here as it takes a relative timespec. 111 * 112 * Note! For non-resuming waits, we can skip calculating the absolute 113 * time ASSUMING it is only needed for timeout adjustments 114 * after an -EINTR return. 115 */ 116 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 117 { 118 if ( sizeof(pDeadline->tv_sec) >= sizeof(uint64_t) 119 || uTimeout < (uint64_t)UINT32_MAX * RT_MS_1SEC) 120 { 121 pDeadline->tv_sec = uTimeout / RT_MS_1SEC; 122 pDeadline->tv_nsec = (uTimeout % RT_MS_1SEC) & RT_NS_1MS; 123 uTimeout *= RT_NS_1MS; 124 } 125 else 126 return UINT64_MAX; 127 } 128 else 129 { 130 Assert(fFlags & RTSEMWAIT_FLAGS_NANOSECS); 131 if ( sizeof(pDeadline->tv_sec) >= sizeof(uint64_t) 132 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC) 133 { 134 pDeadline->tv_sec = uTimeout / RT_NS_1SEC; 135 pDeadline->tv_nsec = uTimeout % RT_NS_1SEC; 136 } 137 else 138 return UINT64_MAX; 139 } 140 141 #ifdef RT_STRICT 142 if (!(fFlags & RTSEMWAIT_FLAGS_RESUME)) 143 *pnsAbsTimeout = uTimeout; 144 else 145 #endif 146 *pnsAbsTimeout = RTTimeNanoTS() + uTimeout; /* Note! only relevant for relative waits (FUTEX_WAIT). */ 147 } 148 else 149 { 150 /* Absolute deadline: */ 151 Assert(fFlags & RTSEMWAIT_FLAGS_ABSOLUTE); 152 if (fCanUseWaitBitSet == true) 153 { 154 /* 155 * Use FUTEX_WAIT_BITSET as it takes an absolute deadline. 156 */ 157 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 158 { 159 if ( sizeof(pDeadline->tv_sec) >= sizeof(uint64_t) 160 || uTimeout < (uint64_t)UINT32_MAX * RT_MS_1SEC) 161 { 162 pDeadline->tv_sec = uTimeout / RT_MS_1SEC; 163 pDeadline->tv_nsec = (uTimeout % RT_MS_1SEC) & RT_NS_1MS; 164 } 165 else 166 return UINT64_MAX; 167 } 168 else 169 { 170 Assert(fFlags & RTSEMWAIT_FLAGS_NANOSECS); 171 if ( sizeof(pDeadline->tv_sec) >= sizeof(uint64_t) 172 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC) 173 { 174 pDeadline->tv_sec = uTimeout / RT_NS_1SEC; 175 pDeadline->tv_nsec = uTimeout % RT_NS_1SEC; 176 } 177 else 178 return UINT64_MAX; 179 } 180 *pnsAbsTimeout = uTimeout; 181 *piWaitOp = FUTEX_WAIT_BITSET; 182 *puWaitVal3 = UINT32_MAX; 183 return RT_MS_1SEC; /* Whatever non-zero; Whole point is not calling RTTimeNanoTS() in this path. */ 184 } 185 186 /* 187 * FUTEX_WAIT_BITSET is not available, so use FUTEX_WAIT with a 188 * relative timeout. 189 */ 190 if (fFlags & RTSEMWAIT_FLAGS_MILLISECS) 191 { 192 if (uTimeout < UINT64_MAX / RT_NS_1MS) 193 uTimeout *= RT_NS_1MS; 194 else 195 return UINT64_MAX; 196 } 197 198 uint64_t const u64Now = RTTimeNanoTS(); 199 if (u64Now < uTimeout) 200 { 201 *pnsAbsTimeout = uTimeout; 202 uTimeout -= u64Now; 203 } 204 else 205 return 0; 206 207 if ( sizeof(pDeadline->tv_sec) >= sizeof(uint64_t) 208 || uTimeout < (uint64_t)UINT32_MAX * RT_NS_1SEC) 209 { 210 pDeadline->tv_sec = uTimeout / RT_NS_1SEC; 211 pDeadline->tv_nsec = uTimeout % RT_NS_1SEC; 212 } 213 else 214 return UINT64_MAX; 215 } 216 217 *piWaitOp = FUTEX_WAIT; 218 *puWaitVal3 = 0; 219 return uTimeout; 220 } 221 73 222 #endif /* !IPRT_INCLUDED_SRC_r3_linux_semwait_linux_h */ 74 223
Note:
See TracChangeset
for help on using the changeset viewer.