Changeset 25515 in vbox
- Timestamp:
- Dec 20, 2009 2:44:16 PM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/generic/semrw-generic.cpp
r25513 r25515 214 214 unsigned cMilliesInitial = cMillies; 215 215 uint64_t tsStart = 0; 216 if (cMillies != RT_INDEFINITE_WAIT )216 if (cMillies != RT_INDEFINITE_WAIT && cMillies != 0) 217 217 tsStart = RTTimeNanoTS(); 218 218 … … 227 227 } 228 228 229 /* 230 * Check if the state of affairs allows read access. 231 * Do not block further readers if there is a writer waiting, as 232 * that will break/deadlock reader recursion. 233 */ 234 if (!pThis->cWrites 235 /** @todo && ( pThis->cReads 236 * || !pThis->cWritesWaiting) ?? - making sure not to race waiting 237 * writers. */ 238 ) 239 { 240 pThis->cReads++; 241 242 RTCritSectLeave(&pThis->CritSect); 243 return VINF_SUCCESS; 244 } 245 246 if (pThis->Writer == Self) 247 { 248 pThis->cWriterReads++; 249 250 RTCritSectLeave(&pThis->CritSect); 251 return VINF_SUCCESS; 252 } 253 254 RTCritSectLeave(&pThis->CritSect); 255 256 /* 257 * Wait till it's ready for reading. 258 */ 259 if (cMillies == 0) 260 return VERR_TIMEOUT; 261 229 262 for (;;) 230 263 { 264 if (cMillies != RT_INDEFINITE_WAIT) 265 { 266 int64_t tsDelta = RTTimeNanoTS() - tsStart; 267 if (tsDelta >= 1000000) 268 { 269 tsDelta /= 1000000; 270 if ((uint64_t)tsDelta < cMilliesInitial) 271 cMilliesInitial = (unsigned)tsDelta; 272 else 273 cMilliesInitial = 1; 274 } 275 } 276 int rcWait = rc = RTSemEventMultiWait(pThis->ReadEvent, cMillies); 277 if (RT_FAILURE(rc) && rc != VERR_TIMEOUT) /* handle timeout below */ 278 { 279 AssertMsgRC(rc, ("RTSemEventMultiWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 280 break; 281 } 282 283 if (pThis->u32Magic != RTSEMRW_MAGIC) 284 { 285 rc = VERR_SEM_DESTROYED; 286 break; 287 } 288 231 289 /* 232 * Check if the state of affairs allows read access. 233 * Do not block further readers if there is a writer waiting, as 234 * that will break/deadlock reader recursion. 290 * Re-take critsect and repeate the exact same checks as we did before 291 * the loop. 235 292 */ 293 rc = RTCritSectEnter(&pThis->CritSect); 294 if (RT_FAILURE(rc)) 295 { 296 AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 297 break; 298 } 299 236 300 if (!pThis->cWrites 237 301 /** @todo && ( pThis->cReads … … 257 321 258 322 /* 259 * Wait till it's ready for reading.323 * Quit if the wait already timed out. 260 324 */ 261 if (cMillies != RT_INDEFINITE_WAIT) 262 { 263 int64_t tsDelta = RTTimeNanoTS() - tsStart; 264 if (tsDelta >= 1000000) 265 { 266 cMillies = cMilliesInitial - (unsigned)(tsDelta / 1000000); 267 if (cMillies > cMilliesInitial) 268 cMillies = cMilliesInitial ? 1 : 0; 269 } 270 } 271 rc = RTSemEventMultiWait(pThis->ReadEvent, cMillies); 272 if (RT_FAILURE(rc) && rc != VERR_TIMEOUT) 273 { 274 AssertMsgRC(rc, ("RTSemEventMultiWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 275 break; 276 } 277 278 if (pThis->u32Magic != RTSEMRW_MAGIC) 279 { 280 rc = VERR_SEM_DESTROYED; 281 break; 282 } 283 284 /* 285 * Re-take critsect. 286 */ 287 rc = RTCritSectEnter(&pThis->CritSect); 288 if (RT_FAILURE(rc)) 289 { 290 AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 325 if (rcWait == VERR_TIMEOUT) 326 { 327 rc = VERR_TIMEOUT; 291 328 break; 292 329 } … … 379 416 380 417 /* 418 * Check if the state of affairs allows write access. 419 */ 420 if (!pThis->cReads && (!pThis->cWrites || pThis->Writer == Self)) 421 { 422 /* 423 * Reset the reader event semaphore if necessary. 424 */ 425 if (pThis->fNeedResetReadEvent) 426 { 427 pThis->fNeedResetReadEvent = false; 428 rc = RTSemEventMultiReset(pThis->ReadEvent); 429 AssertMsgRC(rc, ("Failed to reset readers, rwsem %p, rc=%Rrc.\n", RWSem, rc)); 430 } 431 432 pThis->cWrites++; 433 pThis->Writer = Self; 434 435 RTCritSectLeave(&pThis->CritSect); 436 return VINF_SUCCESS; 437 } 438 439 /* 381 440 * Signal writer presence. 382 441 */ 383 pThis->cWritesWaiting++; 442 if (cMillies != 0) 443 pThis->cWritesWaiting++; 444 445 RTCritSectLeave(&pThis->CritSect); 446 447 /* 448 * Wait till it's ready for writing. 449 */ 450 if (cMillies == 0) 451 return VERR_TIMEOUT; 384 452 385 453 for (;;) 386 454 { 455 if (cMillies != RT_INDEFINITE_WAIT) 456 { 457 int64_t tsDelta = RTTimeNanoTS() - tsStart; 458 if (tsDelta >= 1000000) 459 { 460 tsDelta /= 1000000; 461 if ((uint64_t)tsDelta < cMilliesInitial) 462 cMilliesInitial = (unsigned)tsDelta; 463 else 464 cMilliesInitial = 1; 465 } 466 } 467 int rcWait = rc = RTSemEventWait(pThis->WriteEvent, cMillies); 468 if (RT_UNLIKELY(RT_FAILURE_NP(rc) && rc != VERR_TIMEOUT)) /* timeouts are handled below */ 469 { 470 AssertMsgRC(rc, ("RTSemEventWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 471 break; 472 } 473 474 if (RT_UNLIKELY(pThis->u32Magic != RTSEMRW_MAGIC)) 475 { 476 rc = VERR_SEM_DESTROYED; 477 break; 478 } 479 387 480 /* 388 * Check if the state of affairs allows write access.481 * Re-take critsect and repeate the check we did prior to this loop. 389 482 */ 483 rc = RTCritSectEnter(&pThis->CritSect); 484 if (RT_FAILURE(rc)) 485 { 486 AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 487 break; 488 } 489 390 490 if (!pThis->cReads && (!pThis->cWrites || pThis->Writer == Self)) 391 491 { … … 402 502 pThis->cWrites++; 403 503 pThis->Writer = Self; 404 /* We're not waiting, so decrease counter. */405 504 pThis->cWritesWaiting--; 505 406 506 RTCritSectLeave(&pThis->CritSect); 407 507 return VINF_SUCCESS; … … 411 511 412 512 /* 413 * Wait till it's ready for writing.513 * Quit if the wait already timed out. 414 514 */ 415 if (cMillies != RT_INDEFINITE_WAIT && cMillies != 0) 416 { 417 int64_t tsDelta = RTTimeNanoTS() - tsStart; 418 if (tsDelta >= 1000000) 419 { 420 cMillies = cMilliesInitial - (unsigned)(tsDelta / 1000000); 421 if (cMillies > cMilliesInitial) 422 cMillies = cMilliesInitial ? 1 : 0; 423 } 424 } 425 rc = RTSemEventWait(pThis->WriteEvent, cMillies); 426 if (RT_UNLIKELY(RT_FAILURE_NP(rc) && rc != VERR_TIMEOUT)) 427 { 428 AssertMsgRC(rc, ("RTSemEventWait failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 429 break; 430 } 431 432 if (RT_UNLIKELY(pThis->u32Magic != RTSEMRW_MAGIC)) 433 { 434 rc = VERR_SEM_DESTROYED; 435 break; 436 } 437 438 /* 439 * Re-take critsect. 440 */ 441 rc = RTCritSectEnter(&pThis->CritSect); 442 if (RT_FAILURE(rc)) 443 { 444 AssertMsgFailed(("RTCritSectEnter failed on rwsem %p, rc=%Rrc\n", RWSem, rc)); 445 break; 446 } 447 // AssertMsg(!pThis->cReads, ("We woke up and there are readers around!\n")); 515 if (rcWait == VERR_TIMEOUT) 516 { 517 rc = VERR_TIMEOUT; 518 break; 519 } 448 520 } 449 521
Note:
See TracChangeset
for help on using the changeset viewer.