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.

129 lines
3.0 KiB

  1. /*==========================================================================*\
  2. Module: spinlock.h
  3. Copyright Microsoft Corporation 1996, All Rights Reserved.
  4. Author: mikepurt
  5. Descriptions: Implements a spin lock that can be used on Shared Memory
  6. \*==========================================================================*/
  7. #ifndef __SPINLOCK_H__
  8. #define __SPINLOCK_H__
  9. //
  10. // This correct value of the spin count will depend heavily on how much time
  11. // is spent holding the lock.
  12. //
  13. const DWORD DEFAULT_SPIN_COUNT = 500; // ??
  14. const DWORD SPIN_UNLOCKED = 0;
  15. /*$--CSpinLock==============================================================*\
  16. \*==========================================================================*/
  17. class CSpinLock
  18. {
  19. public:
  20. void Initialize(IN DWORD cMaxSpin = DEFAULT_SPIN_COUNT);
  21. void Acquire();
  22. void Relinquish();
  23. void ResetIfOwnedByOtherProcess();
  24. private:
  25. BOOL m_fMultiProc;
  26. DWORD m_cMaxSpin;
  27. volatile DWORD m_dwLock;
  28. };
  29. /*$--CSpinLock::Initialize==================================================*\
  30. \*==========================================================================*/
  31. inline
  32. void
  33. CSpinLock::Initialize(IN DWORD cMaxSpin)
  34. {
  35. SYSTEM_INFO si;
  36. GetSystemInfo(&si);
  37. m_fMultiProc = (si.dwNumberOfProcessors > 1);
  38. m_dwLock = SPIN_UNLOCKED;
  39. m_cMaxSpin = cMaxSpin;
  40. }
  41. /*$--CSpinLock::Acquire=====================================================*\
  42. \*==========================================================================*/
  43. inline
  44. void
  45. CSpinLock::Acquire()
  46. {
  47. DWORD cSpin = m_cMaxSpin;
  48. DWORD dwLockId = GetCurrentProcessId();
  49. while(InterlockedCompareExchange((LONG *)&m_dwLock,
  50. dwLockId,
  51. SPIN_UNLOCKED))
  52. {
  53. // We should only spin if we're running on a multiprocessor
  54. if (m_fMultiProc)
  55. {
  56. if (cSpin--)
  57. continue;
  58. cSpin = m_cMaxSpin;
  59. }
  60. Sleep(0); // Deschedule ourselves and let whomever has the lock get out
  61. }
  62. }
  63. /*$--CSpinLock::Relinquish==================================================*\
  64. \*==========================================================================*/
  65. inline
  66. void
  67. CSpinLock::Relinquish()
  68. {
  69. Assert(m_dwLock);
  70. m_dwLock = SPIN_UNLOCKED;
  71. }
  72. /*$--CSpinLock::ResetIfOwnedByOtherProcess==================================*\
  73. This method is needed to reset the spin lock in the case where it was being
  74. held by a process that died and didn't have a chance to relinquish it.
  75. \*==========================================================================*/
  76. inline
  77. void
  78. CSpinLock::ResetIfOwnedByOtherProcess()
  79. {
  80. // If it's not locked by us, then reset it.
  81. if ((DWORD)m_dwLock != GetCurrentProcessId())
  82. m_dwLock = SPIN_UNLOCKED;
  83. }
  84. #endif // __SPINLOCK_H__