Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

454 lines
10 KiB

/*++
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_