void DrCriticalSectionBase::SetCriticalSectionLoggingParameters( bool logUsage, DrTimeInterval logHeldTooLongTimeout ) { _logHeldTooLongTimeoutMs = DrGetTimerMsFromInterval(logHeldTooLongTimeout); _logUsage = logUsage; }
void DrCriticalSectionBase::Init( __in PCSTR name, DWORD spinCount, bool logUsage, DrTimeInterval logHeldTooLongTimeout ) { _name = (name != NULL) ? name : "UnknownCritSec"; _logUsage = logUsage; _logHeldTooLongTimeoutMs = DrGetTimerMsFromInterval(logHeldTooLongTimeout); _lastFunctionName = NULL; _lastFileName = NULL; _lastLineNumber = 0; _enterTimeMs = 0; LogAssert( InitializeCriticalSectionAndSpinCount( this, spinCount ) ); }
void RChannelFifoWriter::Drain(DrTimeInterval csTimeOut, RChannelItemRef* pReturnItem) { DrTimeStamp startTime = DrGetCurrentTimeStamp(); bool waitForWriterDrain = false; { AutoCriticalSection acs(&m_baseDR); LogAssert(m_writerState == WS_Running); LogAssert(m_writerTerminationItem != NULL); LogAssert(m_availableUnits == 0); if (m_supplierState == SS_Running && m_outstandingUnits == 0) { LogAssert(m_blockedList.IsEmpty()); } if (m_outstandingUnits > 0 || m_blockedList.IsEmpty() == false) { LogAssert(m_terminationUnit != NULL); m_writerState = WS_Draining; waitForWriterDrain = true; } } if (waitForWriterDrain) { DWORD dRet = ::WaitForSingleObject(m_writerDrainEvent, INFINITE); LogAssert(dRet == WAIT_OBJECT_0); } { AutoCriticalSection acs(&m_baseDR); LogAssert(m_outstandingUnits == 0); LogAssert(m_blockedList.IsEmpty()); LogAssert(m_availableUnits == 0); LogAssert(m_reader != NULL); LogAssert(m_outstandingUnits == 0); LogAssert(m_terminationUnit == NULL); m_writerState = WS_Stopped; ++m_writerEpoch; m_nextDeliverySequenceNumber = 0; m_nextDataSequenceNumber = 0; } DrTimeStamp currentTime = DrGetCurrentTimeStamp(); DrTimeInterval elapsed = DrGetElapsedTime(startTime, currentTime); if (elapsed < csTimeOut) { DWORD timeOut = DrGetTimerMsFromInterval(csTimeOut - elapsed); DWORD dRet = ::WaitForSingleObject(m_supplierDrainEvent, timeOut); LogAssert(dRet == WAIT_TIMEOUT || dRet == WAIT_OBJECT_0); } if (pReturnItem != NULL) { AutoCriticalSection acs(&m_baseDR); *pReturnItem = m_readerTerminationItem; } }
void DrCriticalSectionBase::SetCriticalSectionLogHeldTooLongTimeout( DrTimeInterval logHeldTooLongTimeout ) { _logHeldTooLongTimeoutMs = DrGetTimerMsFromInterval(logHeldTooLongTimeout); }
bool RChannelReaderImpl::FetchNextItemArray(UInt32 maxArraySize, RChannelItemArrayRef* pItemArray, DrTimeInterval csTimeOut) { ChannelProcessRequestList requestList; ChannelUnitList returnUnitList; DryadHandleListEntry* event = NULL; bool timedOut = false; bool mustBlock = false; bool startSupplier = false; { AutoCriticalSection acs(&m_baseDR); if (m_state != RS_Running) { LogAssert(m_state != RS_Closed); /* return an empty array */ pItemArray->Attach(new RChannelItemArray()); return true; } if (!m_unitList.IsEmpty()) { LogAssert(m_startedSupplier == true); LogAssert(m_handlerList.IsEmpty()); RChannelReaderSyncWaiter dummyHandler(NULL, INVALID_HANDLE_VALUE, NULL); dummyHandler.SetMaximumArraySize(maxArraySize); RChannelProcessRequest dummyRequest(NULL, &dummyHandler, NULL); m_handlerList.InsertAsTail(m_handlerList.CastIn(&dummyRequest)); TransferWaitingItems("FetchNextItemArray", &requestList, &returnUnitList); RChannelProcessRequest* dummyReturn = requestList.CastOut(requestList.RemoveHead()); LogAssert(dummyReturn == &dummyRequest); pItemArray->Set(dummyRequest.GetItemArray()); LogAssert((*pItemArray)->GetNumberOfItems() > 0); } else if (m_writerTerminationItem != NULL || m_readerTerminationItem != NULL) { /* we have already sent a termination item for processing so there aren't going to be any more arriving on the queue and we can return an empty list immediately */ pItemArray->Attach(new RChannelItemArray()); } else if (csTimeOut > DrTimeInterval_Zero) { if (m_startedSupplier == false) { /* when we exit the lock, we will start the supplier since this is the first read we have received. After the supplier has been started we'll set m_startedSupplierEvent to prevent a race condition in Interrupt */ startSupplier = true; BOOL bRet = ::ResetEvent(m_startedSupplierEvent); LogAssert(bRet != 0); m_startedSupplier = true; } /* we are going to block */ mustBlock = true; event = m_eventCache.GetEvent(true); } else { /* there's no item available and a zero timeout --- return an empty list immediately */ pItemArray->Attach(new RChannelItemArray()); LogAssert(csTimeOut == DrTimeInterval_Zero); timedOut = true; } m_unitLatch.AcceptList(&returnUnitList); FOO(&requestList); m_sendLatch.AcceptList(&requestList); } if (startSupplier) { // DrLogI( "Starting Supplier"); m_supplier->StartSupplier(m_prefetchCookie); // DrLogI( "Started Supplier"); BOOL bRet = ::SetEvent(m_startedSupplierEvent); LogAssert(bRet != 0); } DispatchRequests("FetchNextItemArray", &requestList, &returnUnitList); if (mustBlock == false) { LogAssert(event == NULL); } else { LogAssert(event != NULL); *pItemArray = NULL; RChannelReaderSyncWaiter* waiter = new RChannelReaderSyncWaiter(this, event->GetHandle(), pItemArray); this->SupplyHandler(waiter, waiter); DWORD timeOut = DrGetTimerMsFromInterval(csTimeOut); DWORD dRet = ::WaitForSingleObject(event->GetHandle(), timeOut); if (dRet == WAIT_TIMEOUT) { /* when cancel returns it's guaranteed the handler has been called */ this->Cancel(waiter); } else { LogAssert(dRet == WAIT_OBJECT_0); } LogAssert(*pItemArray != NULL); delete waiter; { AutoCriticalSection acs(&m_baseDR); /* save this event in case we need one again in the future */ m_eventCache.ReturnEvent(event); /* even if we actually timed out the wait, the handler may have supplied an item immediately afterwards or during the cancel. We only return a timed out value if there's no item ready but we haven't processed a termination item, so it's worth waiting for another one. */ timedOut = ((*pItemArray)->GetNumberOfItems() == 0 && m_writerTerminationItem == NULL && m_readerTerminationItem == NULL); } } return (!timedOut); }