|
|
/*++
Copyright (c) 1998-2001 Microsoft Corporation
Module Name:
hash.h
Abstract:
The public definition of response cache hash table.
Author:
Alex Chen (alexch) 28-Mar-2001
Revision History:
--*/
#ifndef _HASH_H_
#define _HASH_H_
#include "cachep.h"
#ifdef __cplusplus
extern "C" { #endif
//
// Reader-Writer Spinlock definitions
//
#define RWSL_LOCKED ((ULONG) (-1))
#define RWSL_FREE (0)
typedef struct _RWSPINLOCK { union { struct { // 0 == RWSL_FREE => unowned
// >0 => count of readers (shared)
// <0 == RWSL_LOCKED => exclusively owned
volatile LONG CurrentState;
// all writers, including the one that holds the lock
// exclusively, if at all
volatile LONG WritersWaiting; };
ULONGLONG Alignment; }; } RWSPINLOCK, *PRWSPINLOCK;
//
// Hash Table definitions
//
typedef struct _HASH_BUCKET *PHASHBUCKET;
typedef struct _HASH_TABLE { ULONG Signature; //UL_HASH_TABLE_POOL_TAG
POOL_TYPE PoolType;
SIZE_T NumberOfBytes;
PHASHBUCKET pAllocMem;
PHASHBUCKET pBuckets;
} HASHTABLE, *PHASHTABLE;
#define IS_VALID_HASHTABLE(pHashTable) \
(NULL != (pHashTable) \ && NULL != (pHashTable)->pAllocMem \ && UL_HASH_TABLE_POOL_TAG == (pHashTable)->Signature)
/***************************************************************************++
Routine Description:
Initialize the Reader-Writer lock.
Return Value:
--***************************************************************************/ __inline VOID UlInitializeRWSpinLock( PRWSPINLOCK pRWSpinLock ) { // pRWSpinLock->CurrentState: Number of Readers, RWSL_FREE: 0
pRWSpinLock->CurrentState = RWSL_FREE;
// pRWSpinLock->WritersWaiting: Number of Writers
pRWSpinLock->WritersWaiting = 0; } // UlInitializeRWSpinLock
/***************************************************************************++
Routine Description:
Acquire the Reader lock.
Return Value:
--***************************************************************************/ __inline VOID UlAcquireRWSpinLockShared( PRWSPINLOCK pRWSpinLock ) { LONG CurrentState, WritersWaiting;
while (1) { CurrentState = pRWSpinLock->CurrentState; WritersWaiting = pRWSpinLock->WritersWaiting;
//
// If either (1) write lock is acquired (CurrentState == RWSL_LOCKED)
// or (2) there is a writer waiting for the lock
// then skip it this time and try in a tight loop
//
if ((CurrentState != RWSL_LOCKED) && (WritersWaiting == 0)) { //
// Check if number of readers is unchanged
// increase it by 1
//
if ( CurrentState == (LONG) InterlockedCompareExchange( (PLONG) &pRWSpinLock->CurrentState, CurrentState + 1, CurrentState) ) { return; } else { // BUGBUG: This is bogus on a uniprocessor system.
// We'll spin and spin and spin until this thread's
// quantum is exhausted. We should yield immediately
// so that the thread that holds the lock has a chance
// to proceed and release the lock sooner.
// That's assuming we're running at passive level. If
// we're running at dispatch level and the owning thread
// isn't running, we have a biiiig problem.
// Busy loop
PAUSE_PROCESSOR; continue; } } } } // UlAcquireRWSpinLockShared
/***************************************************************************++
Routine Description:
Release the Reader lock.
Return Value:
--***************************************************************************/ __inline VOID UlReleaseRWSpinLockShared( PRWSPINLOCK pRWSpinLock ) { // decrease number of readers by 1
LONG NewState = InterlockedDecrement((PLONG) &pRWSpinLock->CurrentState); ASSERT(NewState >= 0); } // UlReleaseRWSpinLockShared
/***************************************************************************++
Routine Description:
Acquire the Writer lock.
Return Value:
--***************************************************************************/ __inline VOID UlAcquireRWSpinLockExclusive( PRWSPINLOCK pRWSpinLock ) { //
// First, increment the number of writers by 1
// such that block the readers
// By doing so, writers have the priority over readers.
//
LONG WritersWaiting = InterlockedIncrement( (PLONG) &pRWSpinLock->WritersWaiting);
ASSERT(WritersWaiting > 0); //
// Interlocked change the number of readers to -1 (RWSL_LOCKED)
// loop until done
//
if (pRWSpinLock->CurrentState == RWSL_FREE) { if ( RWSL_FREE == InterlockedCompareExchange( (PLONG) &pRWSpinLock->CurrentState, RWSL_LOCKED, RWSL_FREE) ) { return; } }
while (1) { if (pRWSpinLock->CurrentState == RWSL_FREE) { if ( RWSL_FREE == InterlockedCompareExchange( (PLONG) &pRWSpinLock->CurrentState, RWSL_LOCKED, RWSL_FREE) ) { return; } else { // BUGBUG: see comments above about uniprocessor systems
// Busy loop
PAUSE_PROCESSOR; continue; } } } } // UlAcquireRWSpinLockExclusive
/***************************************************************************++
Routine Description:
Release the Writer lock.
Return Value:
--***************************************************************************/ __inline void UlReleaseRWSpinLockExclusive( PRWSPINLOCK pRWSpinLock ) { LONG OldState, NewWaiting; //
// Update pRWSpinLock->CurrentState and pRWSpinLock->WritersWaiting back
// in the reverse order of AcquireRWSpinLockExclusive()
//
OldState = InterlockedExchange( (PLONG) &pRWSpinLock->CurrentState, RWSL_FREE);
ASSERT(OldState = RWSL_LOCKED);
NewWaiting = InterlockedDecrement((PLONG) &pRWSpinLock->WritersWaiting);
ASSERT(NewWaiting >= 0); } // UlReleaseRWSpinLockExclusive
/***************************************************************************++
Routine Description:
Check if the Reader lock is acquired.
Return Value:
TRUE - Acquired FALSE - NOT Acquired
--***************************************************************************/ __inline BOOLEAN UlIsLockedShared( PRWSPINLOCK pRWSpinLock ) { // BUGBUG: this routine does not prove that THIS thread is one
// of the shared holders of the lock, merely that at least one
// thread holds the lock in a shared state. Perhaps some extra
// instrumentation for debug builds?
return (pRWSpinLock->CurrentState > 0); } // UlIsLockedShared
/***************************************************************************++
Routine Description:
Check if the Writer lock is acquired.
Return Value:
TRUE - Acquired FALSE - NOT Acquired
--***************************************************************************/ __inline BOOLEAN UlIsLockedExclusive( PRWSPINLOCK pRWSpinLock ) { // BUGBUG: this routine does not prove that THIS thread holds the lock
// exclusively, merely that someone does.
BOOLEAN IsLocked = (pRWSpinLock->CurrentState == RWSL_LOCKED);
// If it's locked, then we must have added ourselves to WritersWaiting
ASSERT(!IsLocked || pRWSpinLock->WritersWaiting > 0);
return IsLocked; } // UlIsLockedExclusive
/***************************************************************************++
Routine Description:
Wrapper around RtlEqualUnicodeString
Return Value:
TRUE - Equal FALSE - NOT Equal
--***************************************************************************/ __inline BOOLEAN UlEqualUnicodeString( IN PWSTR pString1, IN PWSTR pString2, IN ULONG StringLength, IN BOOLEAN CaseInSensitive ) { UNICODE_STRING UnicodeString1, UnicodeString2;
UnicodeString1.Length = (USHORT) StringLength; UnicodeString1.MaximumLength = (USHORT) StringLength; UnicodeString1.Buffer = pString1; UnicodeString2.Length = (USHORT) StringLength; UnicodeString2.MaximumLength = (USHORT) StringLength; UnicodeString2.Buffer = pString2;
return RtlEqualUnicodeString( &UnicodeString1, &UnicodeString2, CaseInSensitive ); } // UlEqualUnicodeString
NTSTATUS UlInitializeHashTable( IN OUT PHASHTABLE pHashTable, IN POOL_TYPE PoolType, IN LONG HashTableBits );
VOID UlTerminateHashTable( IN PHASHTABLE pHashTable );
PUL_URI_CACHE_ENTRY UlGetFromHashTable( IN PHASHTABLE pHashTable, IN PURI_KEY pUriKey );
PUL_URI_CACHE_ENTRY UlDeleteFromHashTable( IN PHASHTABLE pHashTable, IN PURI_KEY pUriKey );
ULC_RETCODE UlAddToHashTable( IN PHASHTABLE pHashTable, IN PUL_URI_CACHE_ENTRY pUriCacheEntry );
ULONG UlFilterFlushHashTable( IN PHASHTABLE pHashTable, IN PUL_URI_FILTER pFilterRoutine, IN PVOID pContext );
VOID UlClearHashTable( IN PHASHTABLE pHashTable );
#ifdef __cplusplus
}; // extern "C"
#endif
#endif // _HASH_H_
|