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
129 lines
3.0 KiB
/*==========================================================================*\
|
|
|
|
Module: spinlock.h
|
|
|
|
Copyright Microsoft Corporation 1996, All Rights Reserved.
|
|
|
|
Author: mikepurt
|
|
|
|
Descriptions: Implements a spin lock that can be used on Shared Memory
|
|
|
|
\*==========================================================================*/
|
|
|
|
#ifndef __SPINLOCK_H__
|
|
#define __SPINLOCK_H__
|
|
|
|
//
|
|
// This correct value of the spin count will depend heavily on how much time
|
|
// is spent holding the lock.
|
|
//
|
|
const DWORD DEFAULT_SPIN_COUNT = 500; // ??
|
|
const DWORD SPIN_UNLOCKED = 0;
|
|
|
|
|
|
/*$--CSpinLock==============================================================*\
|
|
|
|
\*==========================================================================*/
|
|
|
|
class CSpinLock
|
|
{
|
|
public:
|
|
|
|
void Initialize(IN DWORD cMaxSpin = DEFAULT_SPIN_COUNT);
|
|
void Acquire();
|
|
void Relinquish();
|
|
void ResetIfOwnedByOtherProcess();
|
|
|
|
private:
|
|
BOOL m_fMultiProc;
|
|
DWORD m_cMaxSpin;
|
|
|
|
volatile DWORD m_dwLock;
|
|
};
|
|
|
|
|
|
|
|
/*$--CSpinLock::Initialize==================================================*\
|
|
|
|
\*==========================================================================*/
|
|
|
|
inline
|
|
void
|
|
CSpinLock::Initialize(IN DWORD cMaxSpin)
|
|
{
|
|
SYSTEM_INFO si;
|
|
|
|
GetSystemInfo(&si);
|
|
m_fMultiProc = (si.dwNumberOfProcessors > 1);
|
|
|
|
m_dwLock = SPIN_UNLOCKED;
|
|
m_cMaxSpin = cMaxSpin;
|
|
}
|
|
|
|
|
|
/*$--CSpinLock::Acquire=====================================================*\
|
|
|
|
|
|
|
|
\*==========================================================================*/
|
|
|
|
inline
|
|
void
|
|
CSpinLock::Acquire()
|
|
{
|
|
DWORD cSpin = m_cMaxSpin;
|
|
DWORD dwLockId = GetCurrentProcessId();
|
|
|
|
|
|
|
|
while(InterlockedCompareExchange((LONG *)&m_dwLock,
|
|
dwLockId,
|
|
SPIN_UNLOCKED))
|
|
{
|
|
// We should only spin if we're running on a multiprocessor
|
|
if (m_fMultiProc)
|
|
{
|
|
if (cSpin--)
|
|
continue;
|
|
cSpin = m_cMaxSpin;
|
|
}
|
|
Sleep(0); // Deschedule ourselves and let whomever has the lock get out
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/*$--CSpinLock::Relinquish==================================================*\
|
|
|
|
\*==========================================================================*/
|
|
|
|
inline
|
|
void
|
|
CSpinLock::Relinquish()
|
|
{
|
|
Assert(m_dwLock);
|
|
|
|
m_dwLock = SPIN_UNLOCKED;
|
|
}
|
|
|
|
|
|
|
|
/*$--CSpinLock::ResetIfOwnedByOtherProcess==================================*\
|
|
|
|
This method is needed to reset the spin lock in the case where it was being
|
|
held by a process that died and didn't have a chance to relinquish it.
|
|
|
|
\*==========================================================================*/
|
|
|
|
inline
|
|
void
|
|
CSpinLock::ResetIfOwnedByOtherProcess()
|
|
{
|
|
// If it's not locked by us, then reset it.
|
|
if ((DWORD)m_dwLock != GetCurrentProcessId())
|
|
m_dwLock = SPIN_UNLOCKED;
|
|
}
|
|
|
|
|
|
#endif // __SPINLOCK_H__
|
|
|