620 lines
13 KiB
C++
620 lines
13 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows NT Security
|
|
// Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
//
|
|
// File: lru.h
|
|
//
|
|
// Contents: LRU cache class definitions
|
|
//
|
|
// History: 22-Dec-97 kirtd Created
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
#if !defined(__LRU_H__)
|
|
#define __LRU_H__
|
|
|
|
#include <lrucache.h>
|
|
|
|
//
|
|
// Forward declaration of LRU cache classes
|
|
//
|
|
|
|
class CLruCache;
|
|
class CLruEntry;
|
|
|
|
typedef CLruCache* PCLRUCACHE;
|
|
typedef CLruEntry* PCLRUENTRY;
|
|
|
|
//
|
|
// LRU cache bucket structure
|
|
//
|
|
|
|
typedef struct _LRU_CACHE_BUCKET {
|
|
|
|
DWORD Usage;
|
|
PCLRUENTRY pList;
|
|
|
|
} LRU_CACHE_BUCKET, *PLRU_CACHE_BUCKET;
|
|
|
|
//
|
|
// CLruEntry class definition
|
|
//
|
|
|
|
class CLruEntry
|
|
{
|
|
public:
|
|
|
|
//
|
|
// Construction
|
|
//
|
|
|
|
CLruEntry (
|
|
IN PCLRUCACHE pCache,
|
|
IN PCRYPT_DATA_BLOB pIdentifier,
|
|
IN LPVOID pvData,
|
|
OUT BOOL& rfResult
|
|
);
|
|
|
|
~CLruEntry ();
|
|
|
|
//
|
|
// Reference counting
|
|
//
|
|
|
|
inline VOID AddRef ();
|
|
inline VOID Release ();
|
|
|
|
//
|
|
// Cache and Bucket access
|
|
//
|
|
|
|
inline PCLRUCACHE Cache ();
|
|
inline PLRU_CACHE_BUCKET Bucket ();
|
|
|
|
//
|
|
// Data access
|
|
//
|
|
|
|
inline PCRYPT_DATA_BLOB Identifier ();
|
|
inline LPVOID Data ();
|
|
|
|
//
|
|
// Link access
|
|
//
|
|
|
|
inline VOID SetPrevPointer (IN PCLRUENTRY pPrevEntry);
|
|
inline VOID SetNextPointer (IN PCLRUENTRY pNextEntry);
|
|
|
|
inline PCLRUENTRY PrevPointer ();
|
|
inline PCLRUENTRY NextPointer ();
|
|
|
|
//
|
|
// LRU usage access
|
|
//
|
|
|
|
inline VOID SetUsage (DWORD Usage);
|
|
inline DWORD Usage ();
|
|
|
|
//
|
|
// Cache Destruction notification
|
|
//
|
|
|
|
inline VOID OnCacheDestruction ();
|
|
|
|
private:
|
|
|
|
//
|
|
// Reference count
|
|
//
|
|
|
|
ULONG m_cRefs;
|
|
|
|
//
|
|
// Cache pointer
|
|
//
|
|
|
|
PCLRUCACHE m_pCache;
|
|
|
|
//
|
|
// Entry information
|
|
//
|
|
|
|
CRYPT_DATA_BLOB m_Identifier;
|
|
LPVOID m_pvData;
|
|
|
|
//
|
|
// Links
|
|
//
|
|
|
|
PCLRUENTRY m_pPrevEntry;
|
|
PCLRUENTRY m_pNextEntry;
|
|
PLRU_CACHE_BUCKET m_pBucket;
|
|
|
|
//
|
|
// Usage
|
|
//
|
|
|
|
DWORD m_Usage;
|
|
};
|
|
|
|
//
|
|
// CLruCache class definition
|
|
//
|
|
|
|
class CLruCache
|
|
{
|
|
public:
|
|
|
|
//
|
|
// Construction
|
|
//
|
|
|
|
CLruCache (
|
|
IN PLRU_CACHE_CONFIG pConfig,
|
|
OUT BOOL& rfResult
|
|
);
|
|
|
|
~CLruCache ();
|
|
|
|
//
|
|
// Clearing the cache
|
|
//
|
|
|
|
VOID PurgeAllEntries (
|
|
IN DWORD dwFlags,
|
|
IN OPTIONAL LPVOID pvRemovalContext
|
|
);
|
|
|
|
//
|
|
// Cache locking
|
|
//
|
|
|
|
inline VOID LockCache ();
|
|
inline VOID UnlockCache ();
|
|
|
|
//
|
|
// LRU enable and disable
|
|
//
|
|
|
|
VOID EnableLruOfEntries (IN OPTIONAL LPVOID pvLruRemovalContext);
|
|
|
|
VOID DisableLruOfEntries ();
|
|
|
|
//
|
|
// Cache entry manipulation
|
|
//
|
|
|
|
VOID InsertEntry (
|
|
IN PCLRUENTRY pEntry,
|
|
IN OPTIONAL LPVOID pvLruRemovalContext
|
|
);
|
|
|
|
VOID RemoveEntry (
|
|
IN PCLRUENTRY pEntry,
|
|
IN DWORD dwFlags,
|
|
IN OPTIONAL LPVOID pvRemovalContext
|
|
);
|
|
|
|
VOID TouchEntry (IN PCLRUENTRY pEntry, IN DWORD dwFlags);
|
|
|
|
//
|
|
// Cache entry retrieval
|
|
//
|
|
|
|
PCLRUENTRY FindEntry (IN PCRYPT_DATA_BLOB pIdentifier, IN BOOL fTouchEntry);
|
|
|
|
PCLRUENTRY NextMatchingEntry (
|
|
IN PCLRUENTRY pPrevEntry,
|
|
IN BOOL fTouchEntry
|
|
);
|
|
|
|
//
|
|
// Cache bucket retrieval
|
|
//
|
|
|
|
inline PLRU_CACHE_BUCKET BucketFromIdentifier (
|
|
IN PCRYPT_DATA_BLOB pIdentifier
|
|
);
|
|
|
|
//
|
|
// Configuration access
|
|
//
|
|
|
|
//
|
|
// Use the configured free function to release the
|
|
// pvData in an entry
|
|
//
|
|
// MOTE: This is called from the CLruEntry destructor
|
|
//
|
|
|
|
inline VOID FreeEntryData (IN LPVOID pvData);
|
|
|
|
//
|
|
// Access the configuration flags
|
|
//
|
|
|
|
inline DWORD Flags ();
|
|
|
|
//
|
|
// Usage clock access
|
|
//
|
|
|
|
inline VOID IncrementUsageClock ();
|
|
inline DWORD UsageClock ();
|
|
|
|
//
|
|
// Walk all cache entries
|
|
//
|
|
|
|
VOID WalkEntries (IN PFN_WALK_ENTRIES pfnWalk, IN LPVOID pvParameter);
|
|
|
|
private:
|
|
|
|
//
|
|
// Cache configuration
|
|
//
|
|
|
|
LRU_CACHE_CONFIG m_Config;
|
|
|
|
//
|
|
// Cache lock
|
|
//
|
|
|
|
CRITICAL_SECTION m_Lock;
|
|
|
|
//
|
|
// Entry count
|
|
//
|
|
|
|
DWORD m_cEntries;
|
|
|
|
//
|
|
// Cache Buckets
|
|
//
|
|
|
|
PLRU_CACHE_BUCKET m_aBucket;
|
|
|
|
//
|
|
// Usage clock
|
|
//
|
|
|
|
DWORD m_UsageClock;
|
|
|
|
//
|
|
// LRU disabled count
|
|
//
|
|
|
|
DWORD m_cLruDisabled;
|
|
|
|
//
|
|
// Private methods
|
|
//
|
|
|
|
VOID RemoveEntryFromBucket (
|
|
IN PLRU_CACHE_BUCKET pBucket,
|
|
IN PCLRUENTRY pEntry,
|
|
IN DWORD dwFlags,
|
|
IN OPTIONAL LPVOID pvRemovalContext
|
|
);
|
|
|
|
PCLRUENTRY FindNextMatchingEntryInBucket (
|
|
IN PLRU_CACHE_BUCKET pBucket,
|
|
IN PCLRUENTRY pCurrent,
|
|
IN PCRYPT_DATA_BLOB pIdentifier,
|
|
IN BOOL fTouchEntry
|
|
);
|
|
|
|
VOID PurgeLeastRecentlyUsed (IN OPTIONAL LPVOID pvLruRemovalContext);
|
|
|
|
inline VOID TouchEntryNoLock (IN PCLRUENTRY pEntry, IN DWORD dwFlags);
|
|
};
|
|
|
|
//
|
|
// Inline functions
|
|
//
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::AddRef, public
|
|
//
|
|
// Synopsis: increment entry reference count
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruEntry::AddRef ()
|
|
{
|
|
InterlockedIncrement( (LONG *)&m_cRefs );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::Release, public
|
|
//
|
|
// Synopsis: decrement entry reference count and if count goes to zero
|
|
// free the entry
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruEntry::Release ()
|
|
{
|
|
if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 )
|
|
{
|
|
delete this;
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::Cache, public
|
|
//
|
|
// Synopsis: return the internal cache pointer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline PCLRUCACHE
|
|
CLruEntry::Cache ()
|
|
{
|
|
return( m_pCache );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::Bucket, public
|
|
//
|
|
// Synopsis: return the internal cache bucket pointer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline PLRU_CACHE_BUCKET
|
|
CLruEntry::Bucket ()
|
|
{
|
|
return( m_pBucket );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::Identifier, public
|
|
//
|
|
// Synopsis: return the internal entry identifier
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline PCRYPT_DATA_BLOB
|
|
CLruEntry::Identifier ()
|
|
{
|
|
return( &m_Identifier );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::Data, public
|
|
//
|
|
// Synopsis: return the internal entry data
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline LPVOID
|
|
CLruEntry::Data ()
|
|
{
|
|
return( m_pvData );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::SetPrevPointer, public
|
|
//
|
|
// Synopsis: set the previous entry pointer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruEntry::SetPrevPointer (IN PCLRUENTRY pPrevEntry)
|
|
{
|
|
m_pPrevEntry = pPrevEntry;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::SetNextPointer, public
|
|
//
|
|
// Synopsis: set the next entry pointer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruEntry::SetNextPointer (IN PCLRUENTRY pNextEntry)
|
|
{
|
|
m_pNextEntry = pNextEntry;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::PrevPointer, public
|
|
//
|
|
// Synopsis: return the previous entry pointer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline PCLRUENTRY
|
|
CLruEntry::PrevPointer ()
|
|
{
|
|
return( m_pPrevEntry );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::NextPointer, public
|
|
//
|
|
// Synopsis: return the next entry pointer
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline PCLRUENTRY
|
|
CLruEntry::NextPointer ()
|
|
{
|
|
return( m_pNextEntry );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::SetUsage, public
|
|
//
|
|
// Synopsis: set the usage on the entry object and on
|
|
// the corresponding cache bucket
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruEntry::SetUsage (IN DWORD Usage)
|
|
{
|
|
m_Usage = Usage;
|
|
m_pBucket->Usage = Usage;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::Usage, public
|
|
//
|
|
// Synopsis: return the internal entry usage
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline DWORD
|
|
CLruEntry::Usage ()
|
|
{
|
|
return( m_Usage );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruEntry::OnCacheDestruction, public
|
|
//
|
|
// Synopsis: cleanup reference to cache that is being destroyed
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruEntry::OnCacheDestruction ()
|
|
{
|
|
m_pCache = NULL;
|
|
m_pBucket = NULL;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::LockCache, public
|
|
//
|
|
// Synopsis: acquire the cache lock
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruCache::LockCache ()
|
|
{
|
|
if ( m_Config.dwFlags & LRU_CACHE_NO_SERIALIZE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
EnterCriticalSection( &m_Lock );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::UnlockCache, public
|
|
//
|
|
// Synopsis: release the cache lock
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruCache::UnlockCache ()
|
|
{
|
|
if ( m_Config.dwFlags & LRU_CACHE_NO_SERIALIZE )
|
|
{
|
|
return;
|
|
}
|
|
|
|
LeaveCriticalSection( &m_Lock );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::BucketFromIdentifier, public
|
|
//
|
|
// Synopsis: retrieve the associated cache bucket given the entry identifier
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline PLRU_CACHE_BUCKET
|
|
CLruCache::BucketFromIdentifier (
|
|
IN PCRYPT_DATA_BLOB pIdentifier
|
|
)
|
|
{
|
|
DWORD Hash = ( *m_Config.pfnHash )( pIdentifier );
|
|
|
|
return( &m_aBucket[ Hash % m_Config.cBuckets ] );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::FreeEntryData, public
|
|
//
|
|
// Synopsis: free the data using the configured free function
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruCache::FreeEntryData (IN LPVOID pvData)
|
|
{
|
|
if ( m_Config.pfnFree != NULL )
|
|
{
|
|
( *m_Config.pfnFree )( pvData );
|
|
}
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::Flags, public
|
|
//
|
|
// Synopsis: access the configured flags
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline DWORD
|
|
CLruCache::Flags ()
|
|
{
|
|
return( m_Config.dwFlags );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::IncrementUsageClock, public
|
|
//
|
|
// Synopsis: increment the usage clock
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruCache::IncrementUsageClock ()
|
|
{
|
|
m_UsageClock += 1;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::UsageClock, public
|
|
//
|
|
// Synopsis: return the usage clock value
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline DWORD
|
|
CLruCache::UsageClock ()
|
|
{
|
|
return( m_UsageClock );
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------
|
|
//
|
|
// Member: CLruCache::TouchEntryNoLock, public
|
|
//
|
|
// Synopsis: touch entry without taking the cache lock
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
inline VOID
|
|
CLruCache::TouchEntryNoLock (IN PCLRUENTRY pEntry, IN DWORD dwFlags)
|
|
{
|
|
if ( !( dwFlags & LRU_SUPPRESS_CLOCK_UPDATE ) )
|
|
{
|
|
IncrementUsageClock();
|
|
}
|
|
|
|
pEntry->SetUsage( UsageClock() );
|
|
}
|
|
|
|
#endif
|
|
|