- Timestamp:
- Dec 18, 2009 9:42:04 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 56181
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/err.h
r25467 r25508 853 853 /** The lock validator detected a deadlock. */ 854 854 #define VERR_SEM_LV_DEADLOCK (-372) 855 /** Not the lock owner according our records. */ 856 #define VERR_SEM_LV_NOT_OWNER (-373) 857 /** An illegal lock upgrade was attempted. */ 858 #define VERR_SEM_LV_UPGRADE (-374) 855 859 /** @} */ 856 860 -
trunk/include/iprt/lockvalidator.h
r25498 r25508 128 128 129 129 /** Pointer to a record of one ownership share. */ 130 typedef struct RTLOCKVALIDATORSHARED REC *PRTLOCKVALIDATORSHAREDREC;130 typedef struct RTLOCKVALIDATORSHARED *PRTLOCKVALIDATORSHARED; 131 131 /** 132 132 * For recording the one ownership share. … … 135 135 { 136 136 /** Magic value (RTLOCKVALIDATORSHAREDONE_MAGIC). */ 137 uint32_t 137 uint32_t u32Magic; 138 138 /** Recursion count */ 139 uint32_t 139 uint32_t cRecursion; 140 140 /** The current owner thread. */ 141 RTTHREAD volatile 141 RTTHREAD volatile hThread; 142 142 /** Pointer to the lock record below us. Only accessed by the owner. */ 143 R3R0PTRTYPE(PRTLOCKVALIDATORREC) 143 R3R0PTRTYPE(PRTLOCKVALIDATORREC) pDown; 144 144 /** Pointer back to the shared record. */ 145 R3R0PTRTYPE(PRTLOCKVALIDATORSHARED REC)pSharedRec;145 R3R0PTRTYPE(PRTLOCKVALIDATORSHARED) pSharedRec; 146 146 #if HC_ARCH_BITS == 32 147 147 /** Reserved. */ 148 RTHCPTR 148 RTHCPTR pvReserved; 149 149 #endif 150 150 /** Source position where the lock was taken. */ 151 RTLOCKVALIDATORSRCPOS 151 RTLOCKVALIDATORSRCPOS SrcPos; 152 152 } RTLOCKVALIDATORSHAREDONE; 153 153 AssertCompileSize(RTLOCKVALIDATORSHAREDONE, HC_ARCH_BITS == 32 ? 24 + 16 : 32 + 32); … … 194 194 } RTLOCKVALIDATORSHARED; 195 195 AssertCompileSize(RTLOCKVALIDATORSHARED, HC_ARCH_BITS == 32 ? 20 + 20 + 8 : 32 + 32); 196 /** Pointer to a RTLOCKVALIDATORSHARED. */197 typedef RTLOCKVALIDATORSHARED *PRTLOCKVALIDATORSHARED;198 196 199 197 -
trunk/src/VBox/Runtime/common/misc/lockvalidator.cpp
r25498 r25508 263 263 264 264 265 /** 266 * Locates a thread in a shared lock record. 267 * 268 * @returns Pointer to the thread record on success, NULL on failure.. 269 * @param pShared The shared lock record. 270 * @param hThread The thread to find. 271 * @param piEntry Where to optionally return the table in index. 272 */ 273 DECLINLINE(PRTLOCKVALIDATORSHAREDONE) 274 rtLockValidatorSharedRecFindThread(PRTLOCKVALIDATORSHARED pShared, RTTHREAD hThread, uint32_t *piEntry) 275 { 276 rtLockValidatorSerializeDetectionEnter(); 277 if (pShared->papOwners) 278 { 279 PRTLOCKVALIDATORSHAREDONE volatile *papOwners = pShared->papOwners; 280 uint32_t const cMax = pShared->cAllocated; 281 for (uint32_t iEntry = 0; iEntry < cMax; iEntry++) 282 { 283 PRTLOCKVALIDATORSHAREDONE pEntry; 284 pEntry = (PRTLOCKVALIDATORSHAREDONE)ASMAtomicUoReadPtr((void * volatile *)&papOwners[iEntry]); 285 if (pEntry && pEntry->hThread == hThread) 286 { 287 rtLockValidatorSerializeDetectionLeave(); 288 if (piEntry) 289 *piEntry = iEntry; 290 return pEntry; 291 } 292 } 293 } 294 rtLockValidatorSerializeDetectionLeave(); 295 return NULL; 296 } 297 298 299 /** 300 * Allocates and initializes a thread entry for the shared lock record. 301 * 302 * @returns The new thread entry. 303 * @param pShared The shared lock record. 304 * @param hThread The thread handle. 305 * @param pSrcPos The source position. 306 */ 307 DECLINLINE(PRTLOCKVALIDATORSHAREDONE) 308 rtLockValidatorSharedRecAllocThread(PRTLOCKVALIDATORSHARED pRead, RTTHREAD hThread, PCRTLOCKVALIDATORSRCPOS pSrcPos) 309 { 310 PRTLOCKVALIDATORSHAREDONE pEntry; 311 312 pEntry = (PRTLOCKVALIDATORSHAREDONE)RTMemAlloc(sizeof(RTLOCKVALIDATORSHAREDONE)); 313 if (pEntry) 314 { 315 pEntry->u32Magic = RTLOCKVALIDATORSHAREDONE_MAGIC; 316 pEntry->cRecursion = 1; 317 pEntry->hThread = hThread; 318 pEntry->pDown = NULL; 319 pEntry->pSharedRec = pRead; 320 #if HC_ARCH_BITS == 32 321 pEntry->pvReserved = NULL; 322 #endif 323 if (pSrcPos) 324 pEntry->SrcPos = *pSrcPos; 325 else 326 rtLockValidatorInitSrcPos(&pEntry->SrcPos); 327 } 328 329 return pEntry; 330 } 331 332 /** 333 * Frees a thread entry allocated by rtLockValidatorSharedRecAllocThread. 334 * 335 * @param pEntry The thread entry. 336 */ 337 DECLINLINE(void) rtLockValidatorSharedRecFreeThread(PRTLOCKVALIDATORSHAREDONE pEntry) 338 { 339 if (pEntry) 340 { 341 rtLockValidatorSerializeDestructEnter(); 342 ASMAtomicWriteU32(&pEntry->u32Magic, RTLOCKVALIDATORSHAREDONE_MAGIC_DEAD); 343 ASMAtomicWriteHandle(&pEntry->hThread, NIL_RTTHREAD); 344 rtLockValidatorSerializeDestructLeave(); 345 346 RTMemFree(pEntry); 347 } 348 } 349 350 351 /** 352 * Make more room in the table. 353 * 354 * @retval true on success 355 * @retval false if we're out of memory or running into a bad race condition 356 * (probably a bug somewhere). No longer holding the lock. 357 * 358 * @param pShared The shared lock record. 359 */ 360 static bool rtLockValidatorSharedRecMakeRoom(PRTLOCKVALIDATORSHARED pShared) 361 { 362 for (unsigned i = 0; i < 1000; i++) 363 { 364 /* 365 * Switch to the other data access direction. 366 */ 367 rtLockValidatorSerializeDetectionLeave(); 368 if (i >= 10) 369 { 370 Assert(i != 10 && i != 100); 371 RTThreadSleep(i >= 100); 372 } 373 rtLockValidatorSerializeDestructEnter(); 374 375 /* 376 * Try grab the privilege to reallocating the table. 377 */ 378 if ( pShared->u32Magic == RTLOCKVALIDATORSHARED_MAGIC 379 && ASMAtomicCmpXchgBool(&pShared->fReallocating, true, false)) 380 { 381 uint32_t cAllocated = pShared->cAllocated; 382 if (cAllocated < pShared->cEntries) 383 { 384 /* 385 * Ok, still not enough space. Reallocate the table. 386 */ 387 #if 0 /** @todo enable this after making sure growing works flawlessly. */ 388 uint32_t cInc = RT_ALIGN_32(pShared->cEntries - cAllocated, 16); 389 #else 390 uint32_t cInc = RT_ALIGN_32(pShared->cEntries - cAllocated, 1); 391 #endif 392 PRTLOCKVALIDATORSHAREDONE *papOwners; 393 papOwners = (PRTLOCKVALIDATORSHAREDONE *)RTMemRealloc((void *)pShared->papOwners, 394 (cAllocated + cInc) * sizeof(void *)); 395 if (!papOwners) 396 { 397 ASMAtomicWriteBool(&pShared->fReallocating, false); 398 rtLockValidatorSerializeDestructLeave(); 399 /* RTMemRealloc will assert */ 400 return false; 401 } 402 403 while (cInc-- > 0) 404 { 405 papOwners[cAllocated] = NULL; 406 cAllocated++; 407 } 408 409 ASMAtomicWritePtr((void * volatile *)&pShared->papOwners, papOwners); 410 ASMAtomicWriteU32(&pShared->cAllocated, cAllocated); 411 } 412 ASMAtomicWriteBool(&pShared->fReallocating, false); 413 } 414 rtLockValidatorSerializeDestructLeave(); 415 416 rtLockValidatorSerializeDetectionEnter(); 417 if (RT_UNLIKELY(pShared->u32Magic != RTLOCKVALIDATORSHARED_MAGIC)) 418 break; 419 420 if (pShared->cAllocated >= pShared->cEntries) 421 return true; 422 } 423 424 rtLockValidatorSerializeDetectionLeave(); 425 AssertFailed(); /* too many iterations or destroyed while racing. */ 426 return false; 427 } 428 429 430 /** 431 * Adds a thread entry to a shared lock record. 432 * 433 * @returns true on success, false on serious race or we're if out of memory. 434 * @param pShared The shared lock record. 435 * @param pEntry The thread entry. 436 */ 437 DECLINLINE(bool) rtLockValidatorSharedRecAddThread(PRTLOCKVALIDATORSHARED pShared, PRTLOCKVALIDATORSHAREDONE pEntry) 438 { 439 rtLockValidatorSerializeDetectionEnter(); 440 if (RT_LIKELY(pShared->u32Magic == RTLOCKVALIDATORSHARED_MAGIC)) /* paranoia */ 441 { 442 if ( ASMAtomicIncU32(&pShared->cEntries) > pShared->cAllocated /** @todo add fudge */ 443 && !rtLockValidatorSharedRecMakeRoom(pShared)) 444 return false; /* the worker leave the lock */ 445 446 PRTLOCKVALIDATORSHAREDONE volatile *papOwners = pShared->papOwners; 447 uint32_t const cMax = pShared->cAllocated; 448 for (unsigned i = 0; i < 100; i++) 449 { 450 for (uint32_t iEntry = 0; iEntry < cMax; iEntry++) 451 { 452 if (ASMAtomicCmpXchgPtr((void * volatile *)&papOwners[iEntry], pEntry, NULL)) 453 { 454 rtLockValidatorSerializeDetectionLeave(); 455 return true; 456 } 457 } 458 Assert(i != 25); 459 } 460 AssertFailed(); 461 } 462 rtLockValidatorSerializeDetectionLeave(); 463 return false; 464 } 465 466 467 /** 468 * Remove a thread entry from a shared lock record. 469 * 470 * @param pShared The shared lock record. 471 * @param pEntry The thread entry to remove. 472 * @param iEntry The last known index. 473 */ 474 DECLINLINE(void) rtLockValidatorSharedRecDelete(PRTLOCKVALIDATORSHARED pShared, PRTLOCKVALIDATORSHAREDONE pEntry, 475 uint32_t iEntry) 476 { 477 rtLockValidatorSerializeDetectionEnter(); 478 if (RT_LIKELY(pShared->u32Magic == RTLOCKVALIDATORSHARED_MAGIC)) 479 { 480 if ( iEntry >= pShared->cAllocated 481 || !ASMAtomicCmpXchgPtr((void * volatile *)&pShared->papOwners[iEntry], NULL, pEntry)) 482 { 483 /* this shouldn't happen yet... */ 484 AssertFailed(); 485 PRTLOCKVALIDATORSHAREDONE volatile *papOwners = pShared->papOwners; 486 uint32_t const cMax = pShared->cAllocated; 487 for (iEntry = 0; iEntry < cMax; iEntry++) 488 if (ASMAtomicCmpXchgPtr((void * volatile *)&papOwners[iEntry], NULL, pEntry)) 489 break; 490 AssertReturnVoidStmt(iEntry < cMax, rtLockValidatorSerializeDetectionLeave()); 491 } 492 uint32_t cNow = ASMAtomicDecU32(&pShared->cEntries); 493 Assert(!(cNow & RT_BIT_32(31))); NOREF(cNow); 494 } 495 rtLockValidatorSerializeDetectionLeave(); 496 } 497 498 265 499 RTDECL(int) RTLockValidatorCheckOrder(PRTLOCKVALIDATORREC pRec, RTTHREAD hThread, PCRTLOCKVALIDATORSRCPOS pSrcPos) 266 500 { … … 294 528 AssertReturn(pRead->u32Magic == RTLOCKVALIDATORSHARED_MAGIC, VERR_SEM_LV_INVALID_PARAMETER); 295 529 AssertReturn(hThread != NIL_RTTHREAD, VERR_SEM_LV_INVALID_PARAMETER); 530 531 /* 532 * Locate the entry for this thread in the table. 533 */ 534 uint32_t iEntry = 0; 535 PRTLOCKVALIDATORSHAREDONE pEntry = rtLockValidatorSharedRecFindThread(pRead, hThread, &iEntry); 536 AssertReturn(pEntry, VERR_SEM_LV_NOT_OWNER); 537 538 /* 539 * Check the release order. 540 */ 541 if (pRead->hClass != NIL_RTLOCKVALIDATORCLASS) 542 { 543 /** @todo order validation */ 544 } 545 546 /* 547 * Release the ownership or unwind a level of recursion. 548 */ 549 Assert(pEntry->cRecursion > 0); 550 if (pEntry->cRecursion > 1) 551 pEntry->cRecursion--; 552 else 553 rtLockValidatorSharedRecDelete(pRead, pEntry, iEntry); 296 554 297 555 return VINF_SUCCESS; … … 414 672 AssertReturnVoid(pRead->u32Magic == RTLOCKVALIDATORSHARED_MAGIC); 415 673 AssertReturnVoid(hThread != NIL_RTTHREAD); 674 675 /* 676 * Recursive? 677 * 678 * Note! This code can be optimized to try avoid scanning the table on 679 * insert. However, that's annoying work that makes the code big, 680 * so it can wait til later sometime. 681 */ 682 PRTLOCKVALIDATORSHAREDONE pEntry = rtLockValidatorSharedRecFindThread(pRead, hThread, NULL); 683 if (pEntry) 684 { 685 pEntry->cRecursion++; 686 return; 687 } 688 689 /* 690 * Allocate a new thread entry and insert it into the table. 691 */ 692 pEntry = rtLockValidatorSharedRecAllocThread(pRead, hThread, pSrcPos); 693 if ( pEntry 694 && !rtLockValidatorSharedRecAddThread(pRead, pEntry)) 695 rtLockValidatorSharedRecFreeThread(pEntry); 416 696 } 417 697 … … 421 701 AssertReturnVoid(pRead->u32Magic == RTLOCKVALIDATORSHARED_MAGIC); 422 702 AssertReturnVoid(hThread != NIL_RTTHREAD); 703 AssertMsgFailed(("Not implemented")); 423 704 } 424 705 … … 612 893 , VERR_SEM_LV_INVALID_PARAMETER); 613 894 895 /* 896 * Check for attempts at doing a read upgrade. 897 */ 898 PRTLOCKVALIDATORSHAREDONE pEntry = rtLockValidatorSharedRecFindThread(pRead, hThread, NULL); 899 if (pEntry) 900 { 901 AssertMsgFailed(("Read lock upgrade at %s(%d) %s %p!\nRead lock take at %s(%d) %s %p!\n", 902 pSrcPos->pszFile, pSrcPos->uLine, pSrcPos->pszFunction, pSrcPos->uId, 903 pEntry->SrcPos.pszFile, pEntry->SrcPos.uLine, pEntry->SrcPos.pszFunction, pEntry->SrcPos.uId)); 904 return VERR_SEM_LV_UPGRADE; 905 } 906 907 908 614 909 return VINF_SUCCESS; 615 910 } … … 636 931 || enmThreadState == RTTHREADSTATE_INITIALIZING /* rtThreadInsert uses locks too */ 637 932 , VERR_SEM_LV_INVALID_PARAMETER); 933 Assert(pWrite->hThread != pThread); 934 638 935 639 936 return VINF_SUCCESS; -
trunk/src/VBox/Runtime/testcase/Makefile.kmk
r25426 r25508 93 93 tstSemMutex \ 94 94 tstSemPingPong \ 95 tstSemRW \ 95 96 tstSems \ 96 97 tstRTSemXRoads \ … … 125 126 tstRTBitOperationsPIC3 \ 126 127 tstInlineAsmPIC \ 127 tstInlineAsmPIC3 \ 128 tstSemRW 128 tstInlineAsmPIC3 129 129 PROGRAMS.l4 += \ 130 130 tstIoCtl
Note:
See TracChangeset
for help on using the changeset viewer.