Пример #1
0
//-----------------------------------------------------------------
// Acquire the lock.
//-----------------------------------------------------------------
void CrstBase::Enter()
{
#ifdef _DEBUG
    PreEnter ();
#endif

    _ASSERTE(IsSafeToTake() || g_fEEShutDown);

#ifdef _DEBUG
    char buffer[100];
    sprintf(buffer, "Enter in crst.h - %s", m_tag);
    CRSTBLOCKCOUNTINCL();
    LOCKCOUNTINCL(buffer);
#endif

    EnterCriticalSection(&m_criticalsection);

    CRSTELOCKCOUNTINCL();

#ifdef _DEBUG
    m_holderthreadid = GetCurrentThreadId();
    m_entercount++;
    PostEnter ();
#endif
}
Пример #2
0
//=====================================================================        
BOOL SimpleRWLock::TryEnterWrite()
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_CAN_TAKE_LOCK;

#ifdef _DEBUG
    PreEnter();
#endif //_DEBUG

    LONG RWLock = InterlockedCompareExchange( &m_RWLock, -1, 0 );

    _ASSERTE (RWLock >= 0 || RWLock == -1);
    
    if( RWLock ) {
        return FALSE;
    }
    
    INCTHREADLOCKCOUNT();
    EE_LOCK_TAKEN(this);

#ifdef _DEBUG
    PostEnter();
#endif //_DEBUG

    ResetWriterWaiting();
    
    return TRUE;
}
Пример #3
0
BOOL SimpleRWLock::TryEnterRead()
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_CAN_TAKE_LOCK;

#ifdef _DEBUG
    PreEnter();
#endif //_DEBUG

    LONG RWLock;

    do {
        RWLock = m_RWLock;
        if( RWLock == -1 ) return FALSE;
        _ASSERTE (RWLock >= 0);
    } while( RWLock != InterlockedCompareExchange( &m_RWLock, RWLock+1, RWLock ));

    INCTHREADLOCKCOUNT();
    EE_LOCK_TAKEN(this);

#ifdef _DEBUG
    PostEnter();
#endif //_DEBUG
    
    return TRUE;
}
Пример #4
0
//=====================================================================        
void SimpleRWLock::EnterRead()
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_CAN_TAKE_LOCK;

    // Custom contract is needed for PostEnter()'s unscoped GC_NoTrigger counter change
#ifdef ENABLE_CONTRACTS_IMPL
    CheckGCNoTrigger();
#endif //ENABLE_CONTRACTS_IMPL 

    GCX_MAYBE_PREEMP(m_gcMode == PREEMPTIVE);

#ifdef _DEBUG
    PreEnter();
#endif //_DEBUG

    DWORD dwSwitchCount = 0;

    while (TRUE)
    {
        // prevent writers from being starved. This assumes that writers are rare and 
        // dont hold the lock for a long time. 
        while (IsWriterWaiting())
        {
            int spinCount = m_spinCount;
            while (spinCount > 0) {
                spinCount--;
                YieldProcessor();
            }
            __SwitchToThread(0, ++dwSwitchCount);
        }

        if (TryEnterRead())
        {
            return;
        }

        DWORD i = g_SpinConstants.dwInitialDuration;
        do
        {
            if (TryEnterRead())
            {
                return;
            }

            if (g_SystemInfo.dwNumberOfProcessors <= 1)
            {
                break;
            }
            // Delay by approximately 2*i clock cycles (Pentium III).
            // This is brittle code - future processors may of course execute this
            // faster or slower, and future code generators may eliminate the loop altogether.
            // The precise value of the delay is not critical, however, and I can't think
            // of a better way that isn't machine-dependent.
            for (int delayCount = i; --delayCount; ) 
            {
                YieldProcessor();           // indicate to the processor that we are spining 
            }

            // exponential backoff: wait a factor longer in the next iteration
            i *= g_SpinConstants.dwBackoffFactor;
        }
        while (i < g_SpinConstants.dwMaximumDuration);

        __SwitchToThread(0, ++dwSwitchCount);
    }
}
Пример #5
0
//=====================================================================        
void SimpleRWLock::EnterWrite()
{
    STATIC_CONTRACT_NOTHROW;
    STATIC_CONTRACT_CAN_TAKE_LOCK;

    // Custom contract is needed for PostEnter()'s unscoped GC_NoTrigger counter change
#ifdef ENABLE_CONTRACTS_IMPL
    CheckGCNoTrigger();
#endif //ENABLE_CONTRACTS_IMPL

    GCX_MAYBE_PREEMP(m_gcMode == PREEMPTIVE);

#ifdef _DEBUG
    PreEnter();
#endif //_DEBUG

    BOOL set = FALSE;

    DWORD dwSwitchCount = 0;

    while (TRUE)
    {
        if (TryEnterWrite())
        {
            return;
        }

        // set the writer waiting word, if not already set, to notify potential
        // readers to wait. Remember, if the word is set, so it can be reset later.
        if (!IsWriterWaiting())
        {
            SetWriterWaiting();
            set = TRUE;
        }

        DWORD i = g_SpinConstants.dwInitialDuration;
        do
        {
            if (TryEnterWrite())
            {
                return;
            }

            if (g_SystemInfo.dwNumberOfProcessors <= 1)
            {
                break;
            }
            // Delay by approximately 2*i clock cycles (Pentium III).
            // This is brittle code - future processors may of course execute this
            // faster or slower, and future code generators may eliminate the loop altogether.
            // The precise value of the delay is not critical, however, and I can't think
            // of a better way that isn't machine-dependent.
            for (int delayCount = i; --delayCount; ) 
            {
                YieldProcessor();           // indicate to the processor that we are spining 
            }

            // exponential backoff: wait a factor longer in the next iteration
            i *= g_SpinConstants.dwBackoffFactor;
        }
        while (i < g_SpinConstants.dwMaximumDuration);

        __SwitchToThread(0, ++dwSwitchCount);
    }
}