Пример #1
0
void DHContext::PrintDeadlock(DHDetails *pDetails, SIZE_T cookie)
{
    ICLRSyncManager *pClrSyncManager = m_pSyncManager->GetCLRSyncManager();

    fprintf(stderr, "A deadlock has occurred; terminating the program. Details below.\r\n");

    // Print details about the attempted acquisition:
    IHostTask *pTask;
    m_pTaskManager->GetCurrentTask((IHostTask**)&pTask);
    fprintf(stderr, "  %x was attempting to acquire %x, which created the cycle\r\n",
        dynamic_cast<DHTask*>(pTask)->GetThreadHandle(), cookie);
    pTask->Release();

    // Now walk through the wait-graph and print details:
    for (DHDetails::iterator walker = pDetails->begin();
        walker != pDetails->end();
        walker++)
    {
        IHostTask *pOwner;
        pClrSyncManager->GetMonitorOwner(walker->second, (IHostTask**)&pOwner);        

        fprintf(stderr, "  %x waits on lock %x (owned by %x)\r\n",
            walker->first->GetThreadHandle(), walker->second,
            dynamic_cast<DHTask*>(pOwner)->GetThreadHandle());

        pOwner->Release();
        walker->first->Release();
    }
}
Пример #2
0
STDMETHODIMP_(VOID) DHContext::EndEnter(SIZE_T cookie)
{
    IHostTask* pCurrentTask;
    m_pTaskManager->GetCurrentTask((IHostTask**)&pCurrentTask);

    // This call is made after the thread has acquired the lock. We simply remove
    // our wait record to indicate that we're no longer waiting for the target lock.
    CrstLock lock(m_pCrst);
    m_pLockWaits->erase(pCurrentTask);
    lock.Exit();

#if LOCK_TRACE
    // If we're tracing, enter a record into the list of currently held locks.
    vector<SIZE_T> *pCurrentLocks = reinterpret_cast<vector<SIZE_T>*>(TlsGetValue(m_dwTlsCurrentLocks));
    if (!pCurrentLocks)
    {
        pCurrentLocks = new vector<SIZE_T>;
        TlsSetValue(m_dwTlsCurrentLocks, pCurrentLocks);
    }
    pCurrentLocks->push_back(cookie);

    // And record the uniquely held locks in the active context.
    CrstLock traceLock(m_pLockTraceCrst);
    for (vector<SIZE_T>::iterator lockWalker = pCurrentLocks->begin();
        lockWalker != pCurrentLocks->end();
        lockWalker++)
    {
        // Obtain the list of locks held for the current lock.
        map<SIZE_T, vector<SIZE_T>*>::iterator traceWalker = m_pLockTrace->find(*lockWalker);
        vector<SIZE_T> *pTrace;
        if (traceWalker == m_pLockTrace->end())
        {
            pTrace = new vector<SIZE_T>;
            m_pLockTrace->insert(map<SIZE_T, vector<SIZE_T>*>::value_type(*lockWalker, pTrace));
        }
        else
        {
            pTrace = traceWalker->second;
        }

        // And ensure all locks held from here on are added.
        for (vector<SIZE_T>::iterator heldLocks(lockWalker);
            heldLocks != pCurrentLocks->end();
            heldLocks++)
        {            
            pTrace->push_back(*heldLocks);
        }
    }
    traceLock.Exit();
#endif

    // This may look strange. We Release the underlying IHostTask twice. But this is an
    // operation paired with TryEnter above, which required a call to GetCurrentTask, the
    // result for which we stashed in our map. Thus, we need to Release once for TryEnter
    // and once for the call just above in EndEnter.
    pCurrentTask->Release();
    pCurrentTask->Release();
}