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

  1. /*++
  2. Copyright (C) 1996-2001 Microsoft Corporation
  3. Module Name:
  4. SYNC.CPP
  5. Abstract:
  6. Synchronization
  7. History:
  8. --*/
  9. #include "precomp.h"
  10. #include "sync.h"
  11. #include <cominit.h>
  12. #include <wbemutil.h>
  13. #include <corex.h>
  14. CHaltable::CHaltable() : m_lJustResumed(1), m_dwHaltCount(0), m_csHalt()
  15. {
  16. // This event will be signaled whenever we are not halted
  17. // ======================================================
  18. m_hReady = CreateEvent(NULL, TRUE, TRUE, NULL);
  19. if (NULL == m_hReady) throw CX_MemoryException(); // exception caught in wbemess esssink.cpp
  20. }
  21. CHaltable::~CHaltable()
  22. {
  23. CloseHandle(m_hReady);
  24. }
  25. HRESULT CHaltable::Halt()
  26. {
  27. CInCritSec ics(&m_csHalt); // in critical section
  28. m_dwHaltCount++;
  29. ResetEvent(m_hReady);
  30. return S_OK;
  31. }
  32. HRESULT CHaltable::Resume()
  33. {
  34. CInCritSec ics(&m_csHalt); // in critical section
  35. m_dwHaltCount--;
  36. if(m_dwHaltCount == 0)
  37. {
  38. SetEvent(m_hReady);
  39. m_lJustResumed = 1;
  40. }
  41. return S_OK;
  42. }
  43. HRESULT CHaltable::ResumeAll()
  44. {
  45. CInCritSec ics(&m_csHalt); // in critical section
  46. m_dwHaltCount = 1;
  47. return Resume();
  48. }
  49. HRESULT CHaltable::WaitForResumption()
  50. {
  51. while (WbemWaitForSingleObject(m_hReady, INFINITE) == WAIT_FAILED)
  52. Sleep(0);
  53. if(InterlockedDecrement(&m_lJustResumed) == 0)
  54. {
  55. // The first call after resumption
  56. return S_OK;
  57. }
  58. else
  59. {
  60. // weren't halted
  61. return S_FALSE;
  62. }
  63. }
  64. BOOL CHaltable::IsHalted()
  65. {
  66. // Approximate!
  67. return m_dwHaltCount > 0;
  68. }
  69. CWbemCriticalSection::CWbemCriticalSection( void )
  70. : m_lLock( -1 ), m_lRecursionCount( 0 ), m_dwThreadId( 0 ), m_hEvent( NULL )
  71. {
  72. m_hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );
  73. if ( NULL == m_hEvent )
  74. {
  75. throw CX_MemoryException();
  76. }
  77. }
  78. CWbemCriticalSection::~CWbemCriticalSection( void )
  79. {
  80. if ( NULL != m_hEvent )
  81. {
  82. CloseHandle( m_hEvent );
  83. m_hEvent = NULL;
  84. }
  85. }
  86. BOOL CWbemCriticalSection::Enter( DWORD dwTimeout /* = 0xFFFFFFFF */ )
  87. {
  88. BOOL fReturn = FALSE;
  89. // Only do this once
  90. DWORD dwCurrentThreadId = GetCurrentThreadId();
  91. // Check if we are the current owning thread. We can do this here because
  92. // this test will ONLY succeed in the case where we have a Nested Lock(),
  93. // AND because we are zeroing out the thread id when the lock count hits
  94. // 0.
  95. if( dwCurrentThreadId == m_dwThreadId )
  96. {
  97. // It's us - Bump the lock count
  98. // =============================
  99. InterlockedIncrement( &m_lRecursionCount );
  100. return TRUE;
  101. }
  102. // 0 means we got the lock
  103. if ( 0 == InterlockedIncrement( &m_lLock ) )
  104. {
  105. m_dwThreadId = dwCurrentThreadId;
  106. m_lRecursionCount = 1;
  107. fReturn = TRUE;
  108. }
  109. else
  110. {
  111. // We wait. If we got a signalled event, then we now own the
  112. // critical section. Otherwise, we should perform an InterlockedDecrement
  113. // to account for the Increment that got us here in the first place.
  114. if ( WaitForSingleObject( m_hEvent, dwTimeout ) == WAIT_OBJECT_0 )
  115. {
  116. m_dwThreadId = dwCurrentThreadId;
  117. m_lRecursionCount = 1;
  118. fReturn = TRUE;
  119. }
  120. else
  121. {
  122. InterlockedDecrement( &m_lLock );
  123. }
  124. }
  125. return fReturn;
  126. }
  127. void CWbemCriticalSection::Leave( void )
  128. {
  129. // We don't check the thread id, so we can lock/unlock resources
  130. // across multiple threads
  131. BOOL fReturn = FALSE;
  132. long lRecurse = InterlockedDecrement( &m_lRecursionCount );
  133. // The recursion count hit zero, so it's time to unlock the object
  134. if ( 0 == lRecurse )
  135. {
  136. // If the lock count is >= 0, threads are waiting, so we need to
  137. // signal the event
  138. m_dwThreadId = 0;
  139. if ( InterlockedDecrement( &m_lLock ) >= 0 )
  140. {
  141. SetEvent( m_hEvent );
  142. }
  143. } // If recursion count is at 0
  144. }