windows-nt/Source/XPSP1/NT/inetsrv/iis/lkrhash/inc/klocks.h

477 lines
10 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name :
kLocks.h
Abstract:
A collection of kernel-mode locks for multithreaded access to
data structures that provide the same abstractions as <locks.h>
Author:
George V. Reilly (GeorgeRe) 24-Oct-2000
Environment:
Win32 - Kernel Mode
Project:
Internet Information Server Http.sys
Revision History:
--*/
#ifndef __KLOCKS_H__
#define __KLOCKS_H__
#define LOCKS_KERNEL_MODE
#ifdef __LOCKS_H__
#error Do not #include <locks.h> before <klocks.h>
#endif
#include <locks.h>
//--------------------------------------------------------------------
// CKSpinLock is a mutex lock based on KSPIN_LOCK
class IRTL_DLLEXP CKSpinLock :
public CLockBase<LOCK_KSPINLOCK, LOCK_MUTEX,
LOCK_NON_RECURSIVE, LOCK_WAIT_SPIN, LOCK_QUEUE_KERNEL,
LOCK_CLASS_SPIN
>
{
private:
// BUGBUG: this data must live in non-paged memory
mutable KSPIN_LOCK KSpinLock;
LOCK_INSTRUMENTATION_DECL();
public:
#ifndef LOCK_INSTRUMENTATION
CKSpinLock()
{
KeInitializeSpinLock(&KSpinLock);
}
#else // LOCK_INSTRUMENTATION
CKSpinLock(
const TCHAR* ptszName)
{
KeInitializeSpinLock(&KSpinLock);
LOCK_INSTRUMENTATION_INIT(ptszName);
}
#endif // LOCK_INSTRUMENTATION
#ifdef IRTLDEBUG
~CKSpinLock() {}
#endif // IRTLDEBUG
typedef KIRQL ResultType;
// Acquire an exclusive lock for writing.
// Blocks (if needed) until acquired.
ResultType WriteLock()
{
ResultType OldIrql;
KeAcquireSpinLock(&KSpinLock, &OldIrql);
return OldIrql;
}
// Acquire a (possibly shared) lock for reading.
// Blocks (if needed) until acquired.
ResultType ReadLock()
{
return WriteLock();
}
// Try to acquire an exclusive lock for writing. Returns true
// if successful. Non-blocking.
bool TryWriteLock()
{
return false;
}
// Try to acquire a (possibly shared) lock for reading. Returns true
// if successful. Non-blocking.
bool TryReadLock()
{
return TryWriteLock();
}
// Unlock the lock after a successful call to {,Try}WriteLock().
// Assumes caller owned the lock.
void WriteUnlock(
ResultType OldIrql)
{
KeReleaseSpinLock(&KSpinLock, OldIrql);
}
// Unlock the lock after a successful call to {,Try}ReadLock().
// Assumes caller owned the lock.
void ReadUnlock(
ResultType OldIrql)
{
WriteUnlock(OldIrql);
}
// Is the lock already locked for writing by this thread?
bool IsWriteLocked() const
{
return false; // no way of determining this w/o auxiliary info
}
// Is the lock already locked for reading?
bool IsReadLocked() const
{
return IsWriteLocked();
}
// Is the lock unlocked for writing?
bool IsWriteUnlocked() const
{
return !IsWriteLocked();
}
// Is the lock unlocked for reading?
bool IsReadUnlocked() const
{
return IsWriteUnlocked();
}
// Convert a reader lock to a writer lock
void ConvertSharedToExclusive()
{
// no-op
}
// Convert a writer lock to a reader lock
void ConvertExclusiveToShared()
{
// no-op
}
#ifdef LOCK_DEFAULT_SPIN_IMPLEMENTATION
// Set the spin count for this lock.
// Returns true if successfully set the per-lock spincount, false otherwise
bool SetSpinCount(WORD wSpins)
{
IRTLASSERT((wSpins == LOCK_DONT_SPIN)
|| (wSpins == LOCK_USE_DEFAULT_SPINS)
|| (LOCK_MINIMUM_SPINS <= wSpins
&& wSpins <= LOCK_MAXIMUM_SPINS));
return false;
}
// Return the spin count for this lock.
WORD GetSpinCount() const
{
return sm_wDefaultSpinCount;
}
LOCK_DEFAULT_SPIN_IMPLEMENTATION();
#endif // LOCK_DEFAULT_SPIN_IMPLEMENTATION
static const TCHAR* ClassName() {return _TEXT("CKSpinLock");}
}; // CKSpinLock
//--------------------------------------------------------------------
// CFastMutex is a mutex lock based on FAST_MUTEX
class IRTL_DLLEXP CFastMutex :
public CLockBase<LOCK_FASTMUTEX, LOCK_MUTEX,
LOCK_NON_RECURSIVE, LOCK_WAIT_SPIN, LOCK_QUEUE_KERNEL,
LOCK_CLASS_SPIN
>
{
private:
mutable FAST_MUTEX FastMutex;
LOCK_INSTRUMENTATION_DECL();
public:
#ifndef LOCK_INSTRUMENTATION
CFastMutex()
{
ExInitializeFastMutex(&FastMutex);
}
#else // LOCK_INSTRUMENTATION
CFastMutex(
const TCHAR* ptszName)
{
ExInitializeFastMutex(&FastMutex);
LOCK_INSTRUMENTATION_INIT(ptszName);
}
#endif // LOCK_INSTRUMENTATION
#ifdef IRTLDEBUG
~CFastMutex() {}
#endif // IRTLDEBUG
// Acquire an exclusive lock for writing.
// Blocks (if needed) until acquired.
void WriteLock()
{
ExAcquireFastMutex(&FastMutex);
}
// Acquire a (possibly shared) lock for reading.
// Blocks (if needed) until acquired.
void ReadLock()
{
WriteLock();
}
// Try to acquire an exclusive lock for writing. Returns true
// if successful. Non-blocking.
bool TryWriteLock()
{
return ExTryToAcquireFastMutex(&FastMutex) != FALSE;
}
// Try to acquire a (possibly shared) lock for reading. Returns true
// if successful. Non-blocking.
bool TryReadLock()
{
return TryWriteLock();
}
// Unlock the lock after a successful call to {,Try}WriteLock().
// Assumes caller owned the lock.
void WriteUnlock()
{
ExReleaseFastMutex(&FastMutex);
}
// Unlock the lock after a successful call to {,Try}ReadLock().
// Assumes caller owned the lock.
void ReadUnlock()
{
WriteUnlock();
}
// Is the lock already locked for writing by this thread?
bool IsWriteLocked() const
{
return false; // no way of determining this w/o auxiliary info
}
// Is the lock already locked for reading?
bool IsReadLocked() const
{
return IsWriteLocked();
}
// Is the lock unlocked for writing?
bool IsWriteUnlocked() const
{
return !IsWriteLocked();
}
// Is the lock unlocked for reading?
bool IsReadUnlocked() const
{
return IsWriteUnlocked();
}
// Convert a reader lock to a writer lock
void ConvertSharedToExclusive()
{
// no-op
}
// Convert a writer lock to a reader lock
void ConvertExclusiveToShared()
{
// no-op
}
#ifdef LOCK_DEFAULT_SPIN_IMPLEMENTATION
// Set the spin count for this lock.
// Returns true if successfully set the per-lock spincount, false otherwise
bool SetSpinCount(WORD wSpins)
{
IRTLASSERT((wSpins == LOCK_DONT_SPIN)
|| (wSpins == LOCK_USE_DEFAULT_SPINS)
|| (LOCK_MINIMUM_SPINS <= wSpins
&& wSpins <= LOCK_MAXIMUM_SPINS));
return false;
}
// Return the spin count for this lock.
WORD GetSpinCount() const
{
return sm_wDefaultSpinCount;
}
LOCK_DEFAULT_SPIN_IMPLEMENTATION();
#endif // LOCK_DEFAULT_SPIN_IMPLEMENTATION
static const TCHAR* ClassName() {return _TEXT("CFastMutex");}
}; // CFastMutex
//--------------------------------------------------------------------
// CEResource is a multi-reader, single-writer lock based on ERESOURCE
class IRTL_DLLEXP CEResource :
public CLockBase<LOCK_ERESOURCE, LOCK_MRSW,
LOCK_RECURSIVE, LOCK_WAIT_HANDLE, LOCK_QUEUE_KERNEL,
LOCK_CLASS_SPIN
>
{
private:
mutable ERESOURCE Resource;
public:
CEResource()
{
ExInitializeResourceLite(&Resource);
}
#ifdef LOCK_INSTRUMENTATION
CEResource(
const TCHAR* ptszName)
{
ExInitializeResourceLite(&Resource);
LOCK_INSTRUMENTATION_INIT(ptszName);
}
#endif // LOCK_INSTRUMENTATION
~CEResource()
{
ExDeleteResourceLite(&Resource);
}
inline void
WriteLock()
{
KeEnterCriticalRegion();
ExAcquireResourceExclusiveLite(&Resource, TRUE);
}
inline void
ReadLock()
{
KeEnterCriticalRegion();
ExAcquireResourceSharedLite(&Resource, TRUE);
}
bool ReadOrWriteLock();
inline bool
TryWriteLock()
{
KeEnterCriticalRegion();
BOOLEAN fLocked = ExAcquireResourceExclusiveLite(&Resource, FALSE);
if (! fLocked)
KeLeaveCriticalRegion();
return fLocked != FALSE;
}
inline bool
TryReadLock()
{
KeEnterCriticalRegion();
BOOLEAN fLocked = ExAcquireResourceSharedLite(&Resource, FALSE);
if (! fLocked)
KeLeaveCriticalRegion();
return fLocked != FALSE;
}
inline void
WriteUnlock()
{
ExReleaseResourceLite(&Resource);
KeLeaveCriticalRegion();
}
inline void
ReadUnlock()
{
WriteUnlock();
}
void ReadOrWriteUnlock(bool fIsReadLocked);
// Does current thread hold a write lock?
bool
IsWriteLocked() const
{
return ExIsResourceAcquiredExclusiveLite(&Resource) != FALSE;
}
bool
IsReadLocked() const
{
return ExIsResourceAcquiredSharedLite(&Resource) > 0;
}
bool
IsWriteUnlocked() const
{ return !IsWriteLocked(); }
bool
IsReadUnlocked() const
{ return !IsReadLocked(); }
void
ConvertSharedToExclusive()
{
ReadUnlock();
WriteLock();
}
// There is no such window when converting from a writelock to a readlock
void
ConvertExclusiveToShared()
{
#if 0
ExConvertExclusiveToShared(&Resource);
#else
WriteUnlock();
ReadLock();
#endif
}
#ifdef LOCK_DEFAULT_SPIN_IMPLEMENTATION
bool
SetSpinCount(WORD wSpins)
{return false;}
WORD
GetSpinCount() const
{return sm_wDefaultSpinCount;}
LOCK_DEFAULT_SPIN_IMPLEMENTATION();
#endif // LOCK_DEFAULT_SPIN_IMPLEMENTATION
static const TCHAR*
ClassName()
{return _TEXT("CEResource");}
}; // CEResource
#endif // __KLOCKS_H__