Changeset 25368 in vbox for trunk/src/VBox/Runtime/common
- Timestamp:
- Dec 14, 2009 4:31:40 PM (15 years ago)
- svn:sync-xref-src-repo-rev:
- 55985
- Location:
- trunk/src/VBox/Runtime/common/misc
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/misc/thread.cpp
r25000 r25368 41 41 #include <iprt/alloc.h> 42 42 #include <iprt/assert.h> 43 #include <iprt/lockvalidator.h> 43 44 #include <iprt/semaphore.h> 44 45 #ifdef IN_RING0 … … 48 49 #include <iprt/err.h> 49 50 #include <iprt/string.h> 51 #include "internal/magics.h" 50 52 #include "internal/thread.h" 51 53 #include "internal/sched.h" … … 195 197 196 198 199 /** 200 * Gets the thread state. 201 * 202 * @returns The thread state. 203 * @param pThread The thread. 204 */ 205 DECLINLINE(RTTHREADSTATE) rtThreadGetState(PRTTHREADINT pThread) 206 { 207 return pThread->enmState; 208 } 209 210 211 /** 212 * Sets the thread state. 213 * 214 * @param pThread The thread. 215 * @param enmNewState The new thread state. 216 */ 217 DECLINLINE(void) rtThreadSetState(PRTTHREADINT pThread, RTTHREADSTATE enmNewState) 218 { 219 AssertCompile(sizeof(pThread->enmState) == sizeof(uint32_t)); 220 ASMAtomicWriteU32((uint32_t volatile *)&pThread->enmState, enmNewState); 221 } 197 222 198 223 #ifdef IN_RING3 … … 255 280 { 256 281 rtThreadInsert(pThread, NativeThread); 257 ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_RUNNING);282 rtThreadSetState(pThread, RTTHREADSTATE_RUNNING); 258 283 rtThreadRelease(pThread); 259 284 } … … 376 401 * it should not be reinserted at this point. 377 402 */ 378 if ( pThread->enmState!= RTTHREADSTATE_TERMINATED)403 if (rtThreadGetState(pThread) != RTTHREADSTATE_TERMINATED) 379 404 { 380 405 /* … … 588 613 */ 589 614 pThread->rc = rc; 590 ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_TERMINATED);615 rtThreadSetState(pThread, RTTHREADSTATE_TERMINATED); 591 616 ASMAtomicOrU32(&pThread->fIntFlags, RTTHREADINT_FLAGS_TERMINATED); 592 617 if (pThread->EventTerminated != NIL_RTSEMEVENTMULTI) … … 634 659 * Call thread function and terminate when it returns. 635 660 */ 636 ASMAtomicWriteSize(&pThread->enmState, RTTHREADSTATE_RUNNING);661 rtThreadSetState(pThread, RTTHREADSTATE_RUNNING); 637 662 rc = pThread->pfnThread(pThread, pThread->pvUser); 638 663 … … 1380 1405 1381 1406 /** 1407 * Translate a thread state into a string. 1408 * 1409 * @returns Pointer to a read-only string containing the state name. 1410 * @param enmState The state. 1411 */ 1412 static const char *rtThreadStateName(RTTHREADSTATE enmState) 1413 { 1414 switch (enmState) 1415 { 1416 case RTTHREADSTATE_INVALID: return "INVALID"; 1417 case RTTHREADSTATE_INITIALIZING: return "INITIALIZING"; 1418 case RTTHREADSTATE_TERMINATED: return "TERMINATED"; 1419 case RTTHREADSTATE_RUNNING: return "RUNNING"; 1420 case RTTHREADSTATE_CRITSECT: return "CRITSECT"; 1421 case RTTHREADSTATE_EVENT: return "EVENT"; 1422 case RTTHREADSTATE_EVENT_MULTI: return "EVENT_MULTI"; 1423 case RTTHREADSTATE_FAST_MUTEX: return "FAST_MUTEX"; 1424 case RTTHREADSTATE_MUTEX: return "MUTEX"; 1425 case RTTHREADSTATE_RW_READ: return "RW_READ"; 1426 case RTTHREADSTATE_RW_WRITE: return "RW_WRITE"; 1427 case RTTHREADSTATE_SLEEP: return "SLEEP"; 1428 case RTTHREADSTATE_SPIN_MUTEX: return "SPIN_MUTEX"; 1429 default: return "UnknownThreadState"; 1430 } 1431 } 1432 1433 1434 /** 1382 1435 * Bitch about a deadlock. 1383 1436 * 1384 * @param pThread This thread. 1385 * @param pCur The thread we're deadlocking with. 1386 * @param enmState The sleep state. 1387 * @param u64Block The block data. A pointer or handle. 1388 * @param pszFile Where we are gonna block. 1389 * @param uLine Where we are gonna block. 1390 * @param uId Where we are gonna block. 1391 */ 1392 static void rtThreadDeadlock(PRTTHREADINT pThread, PRTTHREADINT pCur, RTTHREADSTATE enmState, uint64_t u64Block, 1393 const char *pszFile, unsigned uLine, RTUINTPTR uId) 1394 { 1395 AssertMsg1(pCur == pThread ? "!!Deadlock detected!!" : "!!Deadlock exists!!", uLine, pszFile, ""); 1437 * @param pThread This thread. 1438 * @param pCur The thread we're deadlocking with. 1439 * @param enmState The sleep state. 1440 * @param pRec The lock validator record we're going to block on. 1441 * @param RT_SRC_POS_DECL Where we are going to deadlock. 1442 * @param uId Where we are going to deadlock. 1443 */ 1444 static void rtThreadDeadlock(PRTTHREADINT pThread, PRTTHREADINT pCur, RTTHREADSTATE enmState, 1445 PRTLOCKVALIDATORREC pRec, RTHCUINTPTR uId, RT_SRC_POS_DECL) 1446 { 1447 AssertMsg1(pCur == pThread ? "!!Deadlock detected!!" : "!!Deadlock exists!!", iLine, pszFile, pszFunction); 1396 1448 1397 1449 /* … … 1406 1458 * Print info on pCur. Determin next while doing so. 1407 1459 */ 1408 AssertMsg2(" #% d: %RTthrd/%RTnthrd %s: %s(%u) %RTptr\n",1460 AssertMsg2(" #%u: %RTthrd/%RTnthrd %s: %s(%u) %RTptr\n", 1409 1461 iEntry, pCur, pCur->Core.Key, pCur->szName, 1410 pCur->pszBlockFile, pCur->uBlockLine, pCur->uBlockId); 1411 PRTTHREADINT pNext = NULL; 1412 switch (pCur->enmState) 1462 pCur->pszBlockFile, pCur->uBlockLine, pCur->pszBlockFunction, pCur->uBlockId); 1463 PRTTHREADINT pNext = NULL; 1464 RTTHREADSTATE enmCurState = rtThreadGetState(pCur); 1465 switch (enmCurState) 1413 1466 { 1414 1467 case RTTHREADSTATE_CRITSECT: 1468 case RTTHREADSTATE_EVENT: 1469 case RTTHREADSTATE_EVENT_MULTI: 1470 case RTTHREADSTATE_FAST_MUTEX: 1471 case RTTHREADSTATE_MUTEX: 1472 case RTTHREADSTATE_RW_READ: 1473 case RTTHREADSTATE_RW_WRITE: 1474 case RTTHREADSTATE_SPIN_MUTEX: 1415 1475 { 1416 PRTCRITSECT pCritSect = pCur->Block.pCritSect; 1417 if (pCur->enmState != RTTHREADSTATE_CRITSECT) 1476 PRTLOCKVALIDATORREC pCurRec = pCur->Block.pRec; 1477 RTTHREADSTATE enmCurState2 = rtThreadGetState(pCur); 1478 if (enmCurState2 != enmCurState) 1418 1479 { 1419 AssertMsg2("Impossible!!!\n"); 1480 AssertMsg2(" Impossible!!! enmState=%s -> %s (%d)\n", 1481 rtThreadStateName(enmCurState), rtThreadStateName(enmCurState2), enmCurState2); 1420 1482 break; 1421 1483 } 1422 if (VALID_PTR(pCritSect) && RTCritSectIsInitialized(pCritSect)) 1484 if ( VALID_PTR(pCurRec) 1485 && pCurRec->u32Magic == RTLOCKVALIDATORREC_MAGIC) 1423 1486 { 1424 AssertMsg2(" Waiting on CRITSECT %p: Entered %s(%u) %RTptr\n",1425 pCritSect, pCritSect->Strict.pszEnterFile,1426 pC ritSect->Strict.u32EnterLine, pCritSect->Strict.uEnterId);1427 pNext = pC ritSect->Strict.ThreadOwner;1487 AssertMsg2(" Waiting on %s %p [%s]: Entered %s(%u) %s %p\n", 1488 rtThreadStateName(enmCurState), pCurRec->hLock, pCurRec->pszName, 1489 pCurRec->pszFile, pCurRec->uLine, pCurRec->pszFunction, pCurRec->uId); 1490 pNext = pCurRec->hThread; 1428 1491 } 1492 else if (VALID_PTR(pCurRec)) 1493 AssertMsg2(" Waiting on %s pCurRec=%p: invalid magic number: %#x\n", 1494 rtThreadStateName(enmCurState), pCurRec, pCurRec->u32Magic); 1429 1495 else 1430 AssertMsg2(" Waiting on CRITSECT %p: invalid pointer or uninitialized critsect\n", pCritSect); 1496 AssertMsg2(" Waiting on %s pCurRec=%p: invalid pointer\n", 1497 rtThreadStateName(enmCurState), pCurRec); 1431 1498 break; 1432 1499 } 1433 1500 1434 1501 default: 1435 AssertMsg2(" Impossible!!! enmState=% d\n", pCur->enmState);1502 AssertMsg2(" Impossible!!! enmState=%s (%d)\n", rtThreadStateName(enmCurState), enmCurState); 1436 1503 break; 1437 1504 } … … 1466 1533 * This is a RT_STRICT method for debugging locks and detecting deadlocks. 1467 1534 * 1468 * @param hThread The current thread.1469 * @param enmState The sleep state.1470 * @param u64Block The block data. A pointer or handle.1471 * @param pszFileWhere we are blocking.1472 * @param uLineWhere we are blocking.1473 * @param uId Where we are blocking.1474 */ 1475 RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, uint64_t u64Block, 1476 const char *pszFile, unsigned uLine, RTUINTPTR uId) 1535 * @param hThread The current thread. 1536 * @param enmState The sleep state. 1537 * @param pvBlock Pointer to a RTLOCKVALIDATORREC structure. 1538 * @param uId Where we are blocking. 1539 * @param RT_SRC_POS_DECL Where we are blocking. 1540 */ 1541 RTDECL(void) RTThreadBlocking(RTTHREAD hThread, RTTHREADSTATE enmState, 1542 PRTLOCKVALIDATORREC pValidatorRec, RTHCUINTPTR uId, RT_SRC_POS_DECL) 1543 1477 1544 { 1478 1545 PRTTHREADINT pThread = hThread; 1479 1546 Assert(RTTHREAD_IS_SLEEPING(enmState)); 1480 if (pThread && pThread->enmState== RTTHREADSTATE_RUNNING)1547 if (pThread && rtThreadGetState(pThread) == RTTHREADSTATE_RUNNING) 1481 1548 { 1482 1549 /** @todo This has to be serialized! The deadlock detection isn't 100% safe!!! */ 1483 pThread->Block.u64 = u64Block; 1484 pThread->pszBlockFile = pszFile; 1485 pThread->uBlockLine = uLine; 1486 pThread->uBlockId = uId; 1487 ASMAtomicWriteSize(&pThread->enmState, enmState); 1550 pThread->Block.pRec = pValidatorRec; 1551 pThread->pszBlockFunction = pszFunction; 1552 pThread->pszBlockFile = pszFile; 1553 pThread->uBlockLine = iLine; 1554 pThread->uBlockId = uId; 1555 rtThreadSetState(pThread, enmState); 1488 1556 1489 1557 /* … … 1497 1565 PRTTHREADINT pCur; 1498 1566 unsigned cPrevLength = ~0U; 1499 unsigned cEqualRuns = 0;1500 unsigned iParanoia = 256;1567 unsigned cEqualRuns = 0; 1568 unsigned iParanoia = 256; 1501 1569 do 1502 1570 { … … 1508 1576 * Get the next thread. 1509 1577 */ 1578 PRTTHREADINT pNext = NULL; 1510 1579 for (;;) 1511 1580 { 1512 switch (pCur->enmState) 1581 RTTHREADSTATE enmCurState = rtThreadGetState(pCur); 1582 switch (enmCurState) 1513 1583 { 1514 1584 case RTTHREADSTATE_CRITSECT: 1585 case RTTHREADSTATE_EVENT: 1586 case RTTHREADSTATE_EVENT_MULTI: 1587 case RTTHREADSTATE_FAST_MUTEX: 1588 case RTTHREADSTATE_MUTEX: 1589 case RTTHREADSTATE_RW_READ: 1590 case RTTHREADSTATE_RW_WRITE: 1591 case RTTHREADSTATE_SPIN_MUTEX: 1515 1592 { 1516 PRTCRITSECT pCritSect = pCur->Block.pCritSect; 1517 if (pCur->enmState != RTTHREADSTATE_CRITSECT) 1593 PRTLOCKVALIDATORREC pRec = pCur->Block.pRec; 1594 if ( rtThreadGetState(pCur) != enmCurState 1595 || !VALID_PTR(pRec) 1596 || pRec->u32Magic != RTLOCKVALIDATORREC_MAGIC) 1518 1597 continue; 1519 pCur = pCritSect->Strict.ThreadOwner; 1598 pNext = pRec->hThread; 1599 if ( rtThreadGetState(pCur) != enmCurState 1600 || pRec->u32Magic != RTLOCKVALIDATORREC_MAGIC 1601 || pRec->hThread != pNext) 1602 continue; 1520 1603 break; 1521 1604 } 1522 1605 1523 1606 default: 1524 p Cur= NULL;1607 pNext = NULL; 1525 1608 break; 1526 1609 } 1527 1610 break; 1528 1611 } 1612 1613 /* 1614 * If we arrive at the end of the list we're good. 1615 */ 1616 pCur = pNext; 1529 1617 if (!pCur) 1530 1618 return; 1531 1619 1532 1620 /* 1533 * If we've got back to the blocking thread id we've got a deadlock. 1534 * If we've got a chain of more than 256 items, there is some kind of cycle 1535 * in the list, which means that there is already a deadlock somewhere. 1621 * If we've got back to the blocking thread id we've 1622 * got a deadlock. 1536 1623 */ 1537 if (pCur == pThread || cLength >= 256)1624 if (pCur == pThread) 1538 1625 break; 1626 1627 /* 1628 * If we've got a chain of more than 256 items, there is some 1629 * kind of cycle in the list, which means that there is already 1630 * a deadlock somewhere. 1631 */ 1632 if (cLength >= 256) 1633 break; 1634 1539 1635 cLength++; 1540 1636 } … … 1553 1649 * Ok, if we ever get here, it's most likely a genuine deadlock. 1554 1650 */ 1555 rtThreadDeadlock(pThread, pCur, enmState, u64Block, pszFile, uLine, uId);1651 rtThreadDeadlock(pThread, pCur, enmState, pValidatorRec, uId, RT_SRC_POS_ARGS); 1556 1652 } 1557 1653 } … … 1570 1666 RTDECL(void) RTThreadUnblocked(RTTHREAD hThread, RTTHREADSTATE enmCurState) 1571 1667 { 1572 if (hThread && hThread->enmState== enmCurState)1573 ASMAtomicWriteSize(&hThread->enmState, RTTHREADSTATE_RUNNING);1668 if (hThread && rtThreadGetState(hThread) == enmCurState) 1669 rtThreadSetState(hThread, RTTHREADSTATE_RUNNING); 1574 1670 } 1575 1671 RT_EXPORT_SYMBOL(RTThreadUnblocked);
Note:
See TracChangeset
for help on using the changeset viewer.