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.

619 lines
13 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows NT Security
  4. // Copyright (C) Microsoft Corporation, 1997 - 1999
  5. //
  6. // File: lru.h
  7. //
  8. // Contents: LRU cache class definitions
  9. //
  10. // History: 22-Dec-97 kirtd Created
  11. //
  12. //----------------------------------------------------------------------------
  13. #if !defined(__LRU_H__)
  14. #define __LRU_H__
  15. #include <lrucache.h>
  16. //
  17. // Forward declaration of LRU cache classes
  18. //
  19. class CLruCache;
  20. class CLruEntry;
  21. typedef CLruCache* PCLRUCACHE;
  22. typedef CLruEntry* PCLRUENTRY;
  23. //
  24. // LRU cache bucket structure
  25. //
  26. typedef struct _LRU_CACHE_BUCKET {
  27. DWORD Usage;
  28. PCLRUENTRY pList;
  29. } LRU_CACHE_BUCKET, *PLRU_CACHE_BUCKET;
  30. //
  31. // CLruEntry class definition
  32. //
  33. class CLruEntry
  34. {
  35. public:
  36. //
  37. // Construction
  38. //
  39. CLruEntry (
  40. IN PCLRUCACHE pCache,
  41. IN PCRYPT_DATA_BLOB pIdentifier,
  42. IN LPVOID pvData,
  43. OUT BOOL& rfResult
  44. );
  45. ~CLruEntry ();
  46. //
  47. // Reference counting
  48. //
  49. inline VOID AddRef ();
  50. inline VOID Release ();
  51. //
  52. // Cache and Bucket access
  53. //
  54. inline PCLRUCACHE Cache ();
  55. inline PLRU_CACHE_BUCKET Bucket ();
  56. //
  57. // Data access
  58. //
  59. inline PCRYPT_DATA_BLOB Identifier ();
  60. inline LPVOID Data ();
  61. //
  62. // Link access
  63. //
  64. inline VOID SetPrevPointer (IN PCLRUENTRY pPrevEntry);
  65. inline VOID SetNextPointer (IN PCLRUENTRY pNextEntry);
  66. inline PCLRUENTRY PrevPointer ();
  67. inline PCLRUENTRY NextPointer ();
  68. //
  69. // LRU usage access
  70. //
  71. inline VOID SetUsage (DWORD Usage);
  72. inline DWORD Usage ();
  73. //
  74. // Cache Destruction notification
  75. //
  76. inline VOID OnCacheDestruction ();
  77. private:
  78. //
  79. // Reference count
  80. //
  81. ULONG m_cRefs;
  82. //
  83. // Cache pointer
  84. //
  85. PCLRUCACHE m_pCache;
  86. //
  87. // Entry information
  88. //
  89. CRYPT_DATA_BLOB m_Identifier;
  90. LPVOID m_pvData;
  91. //
  92. // Links
  93. //
  94. PCLRUENTRY m_pPrevEntry;
  95. PCLRUENTRY m_pNextEntry;
  96. PLRU_CACHE_BUCKET m_pBucket;
  97. //
  98. // Usage
  99. //
  100. DWORD m_Usage;
  101. };
  102. //
  103. // CLruCache class definition
  104. //
  105. class CLruCache
  106. {
  107. public:
  108. //
  109. // Construction
  110. //
  111. CLruCache (
  112. IN PLRU_CACHE_CONFIG pConfig,
  113. OUT BOOL& rfResult
  114. );
  115. ~CLruCache ();
  116. //
  117. // Clearing the cache
  118. //
  119. VOID PurgeAllEntries (
  120. IN DWORD dwFlags,
  121. IN OPTIONAL LPVOID pvRemovalContext
  122. );
  123. //
  124. // Cache locking
  125. //
  126. inline VOID LockCache ();
  127. inline VOID UnlockCache ();
  128. //
  129. // LRU enable and disable
  130. //
  131. VOID EnableLruOfEntries (IN OPTIONAL LPVOID pvLruRemovalContext);
  132. VOID DisableLruOfEntries ();
  133. //
  134. // Cache entry manipulation
  135. //
  136. VOID InsertEntry (
  137. IN PCLRUENTRY pEntry,
  138. IN OPTIONAL LPVOID pvLruRemovalContext
  139. );
  140. VOID RemoveEntry (
  141. IN PCLRUENTRY pEntry,
  142. IN DWORD dwFlags,
  143. IN OPTIONAL LPVOID pvRemovalContext
  144. );
  145. VOID TouchEntry (IN PCLRUENTRY pEntry, IN DWORD dwFlags);
  146. //
  147. // Cache entry retrieval
  148. //
  149. PCLRUENTRY FindEntry (IN PCRYPT_DATA_BLOB pIdentifier, IN BOOL fTouchEntry);
  150. PCLRUENTRY NextMatchingEntry (
  151. IN PCLRUENTRY pPrevEntry,
  152. IN BOOL fTouchEntry
  153. );
  154. //
  155. // Cache bucket retrieval
  156. //
  157. inline PLRU_CACHE_BUCKET BucketFromIdentifier (
  158. IN PCRYPT_DATA_BLOB pIdentifier
  159. );
  160. //
  161. // Configuration access
  162. //
  163. //
  164. // Use the configured free function to release the
  165. // pvData in an entry
  166. //
  167. // MOTE: This is called from the CLruEntry destructor
  168. //
  169. inline VOID FreeEntryData (IN LPVOID pvData);
  170. //
  171. // Access the configuration flags
  172. //
  173. inline DWORD Flags ();
  174. //
  175. // Usage clock access
  176. //
  177. inline VOID IncrementUsageClock ();
  178. inline DWORD UsageClock ();
  179. //
  180. // Walk all cache entries
  181. //
  182. VOID WalkEntries (IN PFN_WALK_ENTRIES pfnWalk, IN LPVOID pvParameter);
  183. private:
  184. //
  185. // Cache configuration
  186. //
  187. LRU_CACHE_CONFIG m_Config;
  188. //
  189. // Cache lock
  190. //
  191. CRITICAL_SECTION m_Lock;
  192. //
  193. // Entry count
  194. //
  195. DWORD m_cEntries;
  196. //
  197. // Cache Buckets
  198. //
  199. PLRU_CACHE_BUCKET m_aBucket;
  200. //
  201. // Usage clock
  202. //
  203. DWORD m_UsageClock;
  204. //
  205. // LRU disabled count
  206. //
  207. DWORD m_cLruDisabled;
  208. //
  209. // Private methods
  210. //
  211. VOID RemoveEntryFromBucket (
  212. IN PLRU_CACHE_BUCKET pBucket,
  213. IN PCLRUENTRY pEntry,
  214. IN DWORD dwFlags,
  215. IN OPTIONAL LPVOID pvRemovalContext
  216. );
  217. PCLRUENTRY FindNextMatchingEntryInBucket (
  218. IN PLRU_CACHE_BUCKET pBucket,
  219. IN PCLRUENTRY pCurrent,
  220. IN PCRYPT_DATA_BLOB pIdentifier,
  221. IN BOOL fTouchEntry
  222. );
  223. VOID PurgeLeastRecentlyUsed (IN OPTIONAL LPVOID pvLruRemovalContext);
  224. inline VOID TouchEntryNoLock (IN PCLRUENTRY pEntry, IN DWORD dwFlags);
  225. };
  226. //
  227. // Inline functions
  228. //
  229. //+---------------------------------------------------------------------------
  230. //
  231. // Member: CLruEntry::AddRef, public
  232. //
  233. // Synopsis: increment entry reference count
  234. //
  235. //----------------------------------------------------------------------------
  236. inline VOID
  237. CLruEntry::AddRef ()
  238. {
  239. InterlockedIncrement( (LONG *)&m_cRefs );
  240. }
  241. //+---------------------------------------------------------------------------
  242. //
  243. // Member: CLruEntry::Release, public
  244. //
  245. // Synopsis: decrement entry reference count and if count goes to zero
  246. // free the entry
  247. //
  248. //----------------------------------------------------------------------------
  249. inline VOID
  250. CLruEntry::Release ()
  251. {
  252. if ( InterlockedDecrement( (LONG *)&m_cRefs ) == 0 )
  253. {
  254. delete this;
  255. }
  256. }
  257. //+---------------------------------------------------------------------------
  258. //
  259. // Member: CLruEntry::Cache, public
  260. //
  261. // Synopsis: return the internal cache pointer
  262. //
  263. //----------------------------------------------------------------------------
  264. inline PCLRUCACHE
  265. CLruEntry::Cache ()
  266. {
  267. return( m_pCache );
  268. }
  269. //+---------------------------------------------------------------------------
  270. //
  271. // Member: CLruEntry::Bucket, public
  272. //
  273. // Synopsis: return the internal cache bucket pointer
  274. //
  275. //----------------------------------------------------------------------------
  276. inline PLRU_CACHE_BUCKET
  277. CLruEntry::Bucket ()
  278. {
  279. return( m_pBucket );
  280. }
  281. //+---------------------------------------------------------------------------
  282. //
  283. // Member: CLruEntry::Identifier, public
  284. //
  285. // Synopsis: return the internal entry identifier
  286. //
  287. //----------------------------------------------------------------------------
  288. inline PCRYPT_DATA_BLOB
  289. CLruEntry::Identifier ()
  290. {
  291. return( &m_Identifier );
  292. }
  293. //+---------------------------------------------------------------------------
  294. //
  295. // Member: CLruEntry::Data, public
  296. //
  297. // Synopsis: return the internal entry data
  298. //
  299. //----------------------------------------------------------------------------
  300. inline LPVOID
  301. CLruEntry::Data ()
  302. {
  303. return( m_pvData );
  304. }
  305. //+---------------------------------------------------------------------------
  306. //
  307. // Member: CLruEntry::SetPrevPointer, public
  308. //
  309. // Synopsis: set the previous entry pointer
  310. //
  311. //----------------------------------------------------------------------------
  312. inline VOID
  313. CLruEntry::SetPrevPointer (IN PCLRUENTRY pPrevEntry)
  314. {
  315. m_pPrevEntry = pPrevEntry;
  316. }
  317. //+---------------------------------------------------------------------------
  318. //
  319. // Member: CLruEntry::SetNextPointer, public
  320. //
  321. // Synopsis: set the next entry pointer
  322. //
  323. //----------------------------------------------------------------------------
  324. inline VOID
  325. CLruEntry::SetNextPointer (IN PCLRUENTRY pNextEntry)
  326. {
  327. m_pNextEntry = pNextEntry;
  328. }
  329. //+---------------------------------------------------------------------------
  330. //
  331. // Member: CLruEntry::PrevPointer, public
  332. //
  333. // Synopsis: return the previous entry pointer
  334. //
  335. //----------------------------------------------------------------------------
  336. inline PCLRUENTRY
  337. CLruEntry::PrevPointer ()
  338. {
  339. return( m_pPrevEntry );
  340. }
  341. //+---------------------------------------------------------------------------
  342. //
  343. // Member: CLruEntry::NextPointer, public
  344. //
  345. // Synopsis: return the next entry pointer
  346. //
  347. //----------------------------------------------------------------------------
  348. inline PCLRUENTRY
  349. CLruEntry::NextPointer ()
  350. {
  351. return( m_pNextEntry );
  352. }
  353. //+---------------------------------------------------------------------------
  354. //
  355. // Member: CLruEntry::SetUsage, public
  356. //
  357. // Synopsis: set the usage on the entry object and on
  358. // the corresponding cache bucket
  359. //
  360. //----------------------------------------------------------------------------
  361. inline VOID
  362. CLruEntry::SetUsage (IN DWORD Usage)
  363. {
  364. m_Usage = Usage;
  365. m_pBucket->Usage = Usage;
  366. }
  367. //+---------------------------------------------------------------------------
  368. //
  369. // Member: CLruEntry::Usage, public
  370. //
  371. // Synopsis: return the internal entry usage
  372. //
  373. //----------------------------------------------------------------------------
  374. inline DWORD
  375. CLruEntry::Usage ()
  376. {
  377. return( m_Usage );
  378. }
  379. //+---------------------------------------------------------------------------
  380. //
  381. // Member: CLruEntry::OnCacheDestruction, public
  382. //
  383. // Synopsis: cleanup reference to cache that is being destroyed
  384. //
  385. //----------------------------------------------------------------------------
  386. inline VOID
  387. CLruEntry::OnCacheDestruction ()
  388. {
  389. m_pCache = NULL;
  390. m_pBucket = NULL;
  391. }
  392. //+---------------------------------------------------------------------------
  393. //
  394. // Member: CLruCache::LockCache, public
  395. //
  396. // Synopsis: acquire the cache lock
  397. //
  398. //----------------------------------------------------------------------------
  399. inline VOID
  400. CLruCache::LockCache ()
  401. {
  402. if ( m_Config.dwFlags & LRU_CACHE_NO_SERIALIZE )
  403. {
  404. return;
  405. }
  406. EnterCriticalSection( &m_Lock );
  407. }
  408. //+---------------------------------------------------------------------------
  409. //
  410. // Member: CLruCache::UnlockCache, public
  411. //
  412. // Synopsis: release the cache lock
  413. //
  414. //----------------------------------------------------------------------------
  415. inline VOID
  416. CLruCache::UnlockCache ()
  417. {
  418. if ( m_Config.dwFlags & LRU_CACHE_NO_SERIALIZE )
  419. {
  420. return;
  421. }
  422. LeaveCriticalSection( &m_Lock );
  423. }
  424. //+---------------------------------------------------------------------------
  425. //
  426. // Member: CLruCache::BucketFromIdentifier, public
  427. //
  428. // Synopsis: retrieve the associated cache bucket given the entry identifier
  429. //
  430. //----------------------------------------------------------------------------
  431. inline PLRU_CACHE_BUCKET
  432. CLruCache::BucketFromIdentifier (
  433. IN PCRYPT_DATA_BLOB pIdentifier
  434. )
  435. {
  436. DWORD Hash = ( *m_Config.pfnHash )( pIdentifier );
  437. return( &m_aBucket[ Hash % m_Config.cBuckets ] );
  438. }
  439. //+---------------------------------------------------------------------------
  440. //
  441. // Member: CLruCache::FreeEntryData, public
  442. //
  443. // Synopsis: free the data using the configured free function
  444. //
  445. //----------------------------------------------------------------------------
  446. inline VOID
  447. CLruCache::FreeEntryData (IN LPVOID pvData)
  448. {
  449. if ( m_Config.pfnFree != NULL )
  450. {
  451. ( *m_Config.pfnFree )( pvData );
  452. }
  453. }
  454. //+---------------------------------------------------------------------------
  455. //
  456. // Member: CLruCache::Flags, public
  457. //
  458. // Synopsis: access the configured flags
  459. //
  460. //----------------------------------------------------------------------------
  461. inline DWORD
  462. CLruCache::Flags ()
  463. {
  464. return( m_Config.dwFlags );
  465. }
  466. //+---------------------------------------------------------------------------
  467. //
  468. // Member: CLruCache::IncrementUsageClock, public
  469. //
  470. // Synopsis: increment the usage clock
  471. //
  472. //----------------------------------------------------------------------------
  473. inline VOID
  474. CLruCache::IncrementUsageClock ()
  475. {
  476. m_UsageClock += 1;
  477. }
  478. //+---------------------------------------------------------------------------
  479. //
  480. // Member: CLruCache::UsageClock, public
  481. //
  482. // Synopsis: return the usage clock value
  483. //
  484. //----------------------------------------------------------------------------
  485. inline DWORD
  486. CLruCache::UsageClock ()
  487. {
  488. return( m_UsageClock );
  489. }
  490. //+---------------------------------------------------------------------------
  491. //
  492. // Member: CLruCache::TouchEntryNoLock, public
  493. //
  494. // Synopsis: touch entry without taking the cache lock
  495. //
  496. //----------------------------------------------------------------------------
  497. inline VOID
  498. CLruCache::TouchEntryNoLock (IN PCLRUENTRY pEntry, IN DWORD dwFlags)
  499. {
  500. if ( !( dwFlags & LRU_SUPPRESS_CLOCK_UPDATE ) )
  501. {
  502. IncrementUsageClock();
  503. }
  504. pEntry->SetUsage( UsageClock() );
  505. }
  506. #endif