Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

182 lines
4.1 KiB

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
SYNC.CPP
Abstract:
Synchronization
History:
--*/
#include "precomp.h"
#include "sync.h"
#include <cominit.h>
#include <wbemutil.h>
#include <corex.h>
CHaltable::CHaltable() : m_lJustResumed(1), m_dwHaltCount(0), m_csHalt()
{
// This event will be signaled whenever we are not halted
// ======================================================
m_hReady = CreateEvent(NULL, TRUE, TRUE, NULL);
if (NULL == m_hReady) throw CX_MemoryException(); // exception caught in wbemess esssink.cpp
}
CHaltable::~CHaltable()
{
CloseHandle(m_hReady);
}
HRESULT CHaltable::Halt()
{
CInCritSec ics(&m_csHalt); // in critical section
m_dwHaltCount++;
ResetEvent(m_hReady);
return S_OK;
}
HRESULT CHaltable::Resume()
{
CInCritSec ics(&m_csHalt); // in critical section
m_dwHaltCount--;
if(m_dwHaltCount == 0)
{
SetEvent(m_hReady);
m_lJustResumed = 1;
}
return S_OK;
}
HRESULT CHaltable::ResumeAll()
{
CInCritSec ics(&m_csHalt); // in critical section
m_dwHaltCount = 1;
return Resume();
}
HRESULT CHaltable::WaitForResumption()
{
while (WbemWaitForSingleObject(m_hReady, INFINITE) == WAIT_FAILED)
Sleep(0);
if(InterlockedDecrement(&m_lJustResumed) == 0)
{
// The first call after resumption
return S_OK;
}
else
{
// weren't halted
return S_FALSE;
}
}
BOOL CHaltable::IsHalted()
{
// Approximate!
return m_dwHaltCount > 0;
}
CWbemCriticalSection::CWbemCriticalSection( void )
: m_lLock( -1 ), m_lRecursionCount( 0 ), m_dwThreadId( 0 ), m_hEvent( NULL )
{
m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
if ( NULL == m_hEvent )
{
throw CX_MemoryException();
}
}
CWbemCriticalSection::~CWbemCriticalSection( void )
{
if ( NULL != m_hEvent )
{
CloseHandle( m_hEvent );
m_hEvent = NULL;
}
}
BOOL CWbemCriticalSection::Enter( DWORD dwTimeout /* = 0xFFFFFFFF */ )
{
BOOL fReturn = FALSE;
// Only do this once
DWORD dwCurrentThreadId = GetCurrentThreadId();
// Check if we are the current owning thread. We can do this here because
// this test will ONLY succeed in the case where we have a Nested Lock(),
// AND because we are zeroing out the thread id when the lock count hits
// 0.
if( dwCurrentThreadId == m_dwThreadId )
{
// It's us - Bump the lock count
// =============================
InterlockedIncrement( &m_lRecursionCount );
return TRUE;
}
// 0 means we got the lock
if ( 0 == InterlockedIncrement( &m_lLock ) )
{
m_dwThreadId = dwCurrentThreadId;
m_lRecursionCount = 1;
fReturn = TRUE;
}
else
{
// We wait. If we got a signalled event, then we now own the
// critical section. Otherwise, we should perform an InterlockedDecrement
// to account for the Increment that got us here in the first place.
if ( WaitForSingleObject( m_hEvent, dwTimeout ) == WAIT_OBJECT_0 )
{
m_dwThreadId = dwCurrentThreadId;
m_lRecursionCount = 1;
fReturn = TRUE;
}
else
{
InterlockedDecrement( &m_lLock );
}
}
return fReturn;
}
void CWbemCriticalSection::Leave( void )
{
// We don't check the thread id, so we can lock/unlock resources
// across multiple threads
BOOL fReturn = FALSE;
long lRecurse = InterlockedDecrement( &m_lRecursionCount );
// The recursion count hit zero, so it's time to unlock the object
if ( 0 == lRecurse )
{
// If the lock count is >= 0, threads are waiting, so we need to
// signal the event
m_dwThreadId = 0;
if ( InterlockedDecrement( &m_lLock ) >= 0 )
{
SetEvent( m_hEvent );
}
} // If recursion count is at 0
}