174 lines
3.4 KiB
C
174 lines
3.4 KiB
C
/*++
|
|
|
|
Copyright(c) 1999-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
brdgcach.h
|
|
|
|
Abstract:
|
|
|
|
Ethernet MAC level bridge.
|
|
Cache implementation header
|
|
|
|
Author:
|
|
|
|
Mark Aiken
|
|
|
|
Environment:
|
|
|
|
Kernel mode driver
|
|
|
|
Revision History:
|
|
|
|
December 2000 - Original version
|
|
|
|
--*/
|
|
|
|
// ===========================================================================
|
|
//
|
|
// DECLARATIONS
|
|
//
|
|
// ===========================================================================
|
|
|
|
typedef struct _CACHE_ENTRY
|
|
{
|
|
UINT32 key;
|
|
UINT32 data;
|
|
UINT64 hits;
|
|
UINT64 misses;
|
|
} CACHE_ENTRY, *PCACHE_ENTRY;
|
|
|
|
typedef struct _CACHE
|
|
{
|
|
// lock protects all cache fields
|
|
NDIS_SPIN_LOCK lock;
|
|
|
|
// stats
|
|
UINT64 hits;
|
|
UINT64 misses;
|
|
|
|
// 2^shiftFactor is the number of entries
|
|
USHORT shiftFactor;
|
|
|
|
// Pointer to the array of entries
|
|
PCACHE_ENTRY pEntries;
|
|
} CACHE, *PCACHE;
|
|
|
|
//
|
|
// Determines the cache slot for key k in cache c. The slot is determined
|
|
// as the bottom bits of k.
|
|
//
|
|
#define CACHE_INDEX(c, k) (k & ((1 << c->shiftFactor) - 1))
|
|
|
|
// ===========================================================================
|
|
//
|
|
// INLINES
|
|
//
|
|
// ===========================================================================
|
|
|
|
__inline
|
|
VOID
|
|
BrdgClearCache(
|
|
IN PCACHE pCache
|
|
)
|
|
{
|
|
NdisAcquireSpinLock( &pCache->lock );
|
|
memset( pCache->pEntries, 0, sizeof(CACHE_ENTRY) * (1 << pCache->shiftFactor) );
|
|
NdisReleaseSpinLock( &pCache->lock );
|
|
}
|
|
|
|
__inline
|
|
NDIS_STATUS
|
|
BrdgInitializeCache(
|
|
IN PCACHE pCache,
|
|
IN USHORT shiftFactor
|
|
)
|
|
{
|
|
ULONG numEntries = 1 << shiftFactor;
|
|
NDIS_STATUS status;
|
|
|
|
pCache->shiftFactor = shiftFactor;
|
|
NdisAllocateSpinLock( &pCache->lock );
|
|
status = NdisAllocateMemoryWithTag( &pCache->pEntries, sizeof(CACHE_ENTRY) * numEntries, 'gdrB' );
|
|
pCache->hits = 0L;
|
|
pCache->misses = 0L;
|
|
|
|
if( status != NDIS_STATUS_SUCCESS )
|
|
{
|
|
return status;
|
|
}
|
|
|
|
// Zero out the array of entries
|
|
memset( pCache->pEntries, 0, sizeof(CACHE_ENTRY) * (1 << pCache->shiftFactor) );
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
|
|
__inline
|
|
VOID
|
|
BrdgFreeCache(
|
|
IN PCACHE pCache
|
|
)
|
|
{
|
|
NdisFreeMemory( pCache->pEntries, sizeof(CACHE_ENTRY) * (1 << pCache->shiftFactor), 0 );
|
|
}
|
|
|
|
__inline
|
|
UINT32
|
|
BrdgProbeCache(
|
|
IN PCACHE pCache,
|
|
IN UINT32 key
|
|
)
|
|
{
|
|
UINT32 index = CACHE_INDEX(pCache, key);
|
|
PCACHE_ENTRY pEntry = &pCache->pEntries[index];
|
|
UINT32 data = 0L;
|
|
|
|
NdisAcquireSpinLock( &pCache->lock );
|
|
|
|
if( pEntry->key == key )
|
|
{
|
|
data = pEntry->data;
|
|
pEntry->hits++;
|
|
pCache->hits++;
|
|
}
|
|
else
|
|
{
|
|
pEntry->misses++;
|
|
pCache->misses++;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &pCache->lock );
|
|
|
|
return data;
|
|
}
|
|
|
|
__inline
|
|
BOOLEAN
|
|
BrdgUpdateCache(
|
|
IN PCACHE pCache,
|
|
IN UINT32 key,
|
|
IN UINT32 data
|
|
)
|
|
{
|
|
UINT32 index = CACHE_INDEX(pCache, key);
|
|
PCACHE_ENTRY pEntry = &pCache->pEntries[index];
|
|
BOOLEAN bUpdated = FALSE;
|
|
|
|
NdisAcquireSpinLock( &pCache->lock );
|
|
|
|
if( pEntry->key != key &&
|
|
(pEntry->hits < pEntry->misses) )
|
|
{
|
|
pEntry->key = key;
|
|
pEntry->data = data;
|
|
pEntry->hits = 0L;
|
|
pEntry->misses = 0L;
|
|
bUpdated = TRUE;
|
|
}
|
|
|
|
NdisReleaseSpinLock( &pCache->lock );
|
|
|
|
return bUpdated;
|
|
}
|