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.
 
 
 
 
 
 

270 lines
5.7 KiB

/*++ Copyright(c) 2001 Microsoft Corporation
Module Name:
NLB Driver
File Name:
diplist.c
Abstract:
Code to lookup if a DIP is in a list of DIPs, without holding any locks.
History:
04/24/2002 JosephJ Created
--*/
#include <ntddk.h>
#include "wlbsparm.h"
#include "diplist.h"
#include "univ.h"
#include "trace.h"
#include "diplist.tmh"
#define BITS_PER_HASHWORD (8*sizeof((DIPLIST*)0)->BitVector[0])
#define SELECTED_BIT(_hash_value) \
(0x1L << ((_hash_value) % BITS_PER_HASHWORD))
VOID
DipListInitialize(
DIPLIST *pDL
)
//
// Initialize a DIP List
// Must be called with lock held and before calls to any other DIP List
// function.
//
{
NdisZeroMemory(pDL, sizeof(*pDL));
}
VOID
DipListDeinitialize(
DIPLIST *pDL
)
//
// Deinitialize a DIP List
// Must be called with lock held and should be the last call to the DipList.
//
{
//
// Print out stats...
//
TRACE_INFO(
"DIPLIST: NumChecks=%lu NumFastChecks=%lu NumArrayLookups=%lu",
pDL->stats.NumChecks,
pDL->stats.NumFastChecks,
pDL->stats.NumArrayLookups
);
//
// Clear out the structure...
//
NdisZeroMemory(pDL, sizeof(*pDL));
}
VOID
DipListClear(
DIPLIST *pDL
)
//
// Clear all the items in a dip list.
// Must be called with lock held.
//
{
NdisZeroMemory(pDL->Items, sizeof(pDL->Items));
NdisZeroMemory(pDL->BitVector, sizeof(pDL->BitVector));
NdisZeroMemory(pDL->HashTable, sizeof(pDL->HashTable));
}
VOID
DipListSetItem(
DIPLIST *pDL,
ULONG Index,
ULONG Value
)
//
// Set the value of a specific iten the the DIP list.
// Must be called with lock held.
//
{
if (Index >= MAX_ITEMS)
{
ASSERT(!"DipListSetItem Index >= MAX_ITEMS");
goto end;
}
if (pDL->Items[Index] == Value)
{
// nothing to do...
goto end;
}
pDL->Items[Index] = Value;
//
// recompute hash table and bit table.
//
{
UCHAR iItem;
NdisZeroMemory(pDL->BitVector, sizeof(pDL->BitVector));
NdisZeroMemory(pDL->HashTable, sizeof(pDL->HashTable));
for (iItem=0;iItem<MAX_ITEMS;iItem++)
{
Value = pDL->Items[iItem];
if (Value == NULL_VALUE)
{
// Empty slot -- skip;
continue;
}
//
// set bitvalue
//
{
ULONG Hash1 = Value % HASH1_SIZE;
ULONG u = Hash1/BITS_PER_HASHWORD;
pDL->BitVector[u] |= SELECTED_BIT(Hash1);
}
// set hash table entry
{
ULONG Hash2 = Value % HASH2_SIZE;
UCHAR *pItem = pDL->HashTable+Hash2;
while (*pItem!=0)
{
pItem++;
}
//
// Note we set *pItem to 1+Index, so that 0 can be used
// as a sentinel.
//
*pItem = (iItem+1);
}
}
}
end:
return;
}
BOOLEAN
DipListCheckItem(
DIPLIST *pDL,
ULONG Value
)
//
// Returns TRUE IFF an item exists with the specified value.
// May NOT be called with the lock held. If it's called concurrently
// with one of the other functions, the return value is indeterminate.
//
{
BOOLEAN fRet = FALSE;
#if DBG
ULONG fRetDbg = FALSE;
//
// Debug only: search for the Items array for the specified value...
//
{
int i;
ULONG *pItem = pDL->Items;
for (i=0; i<MAX_ITEMS; i++)
{
if (pItem[i] == Value)
{
fRetDbg = TRUE;
break;
}
}
}
pDL->stats.NumChecks++;
#endif
//
// check bitvalue
//
{
ULONG Hash1 = Value % HASH1_SIZE;
ULONG u = Hash1/BITS_PER_HASHWORD;
if (!(pDL->BitVector[u] & SELECTED_BIT(Hash1)))
{
// Can't find it!
#if DBG
pDL->stats.NumFastChecks++;
#endif // DBG
goto end;
}
}
// check hash table
{
ULONG Hash2 = Value % HASH2_SIZE;
UCHAR *pItem = pDL->HashTable+Hash2;
UCHAR iItem;
//
// Because of the size of HashTable, we are guaranteed that the LAST
// entry in the table is ALWAYS NULL. Let's assert this important
// condition...
//
if (pDL->HashTable[(sizeof(pDL->HashTable)/sizeof(pDL->HashTable[0]))-1] != 0)
{
ASSERT(!"DipListCheckItem: End of pDL->HashTable not NULL!");
goto end;
}
while ((iItem = *pItem)!=0)
{
#if DBG
pDL->stats.NumArrayLookups++;
#endif // DBG
//
// Note (iItem-1) is the index in pDL->Items where the
// value is located.
//
if (pDL->Items[iItem-1] == Value)
{
fRet = TRUE; // Found it!
break;
}
pItem++;
}
}
end:
#if DBG
if (fRet != fRetDbg)
{
//
// We can't break here because we don't hold any locks when we
// check, so can't GUARANTEE that fRet == fRetDbg.
// But it'd be highly unusual
//
UNIV_PRINT_CRIT(("DipListCheckItem: fRet (%u) != fRetDbg (%u)", fRet, fRetDbg));
TRACE_CRIT("%!FUNC! fRet (%u) != fRetDbg (%u)", fRet, fRetDbg);
}
#endif //DBG
return fRet;
}