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.

502 lines
11 KiB

  1. /*++
  2. Copyright (c) 1999-2002 Microsoft Corporation
  3. Module Name:
  4. pplasl.h
  5. Abstract:
  6. This file contains definitions and function prototypes of a per-processor
  7. lookaside list manager.
  8. Author:
  9. Shaun Cox (shaunco) 25-Oct-1999
  10. --*/
  11. #ifndef _PPLASL_H_
  12. #define _PPLASL_H_
  13. typedef struct DECLSPEC_ALIGN(UL_CACHE_LINE) _UL_NPAGED_LOOKASIDE_LIST
  14. {
  15. NPAGED_LOOKASIDE_LIST List;
  16. } UL_NPAGED_LOOKASIDE_LIST, *PUL_NPAGED_LOOKASIDE_LIST;
  17. C_ASSERT(sizeof(UL_NPAGED_LOOKASIDE_LIST) % UL_CACHE_LINE == 0);
  18. typedef struct DECLSPEC_ALIGN(UL_CACHE_LINE) _PER_PROC_SLISTS
  19. {
  20. SLIST_HEADER SL;
  21. USHORT MaxDepth; // High water mark
  22. USHORT MinDepth; // Low water mark
  23. LONG Delta; // Delta between the entry serv rate of last two intervals
  24. ULONG EntriesServed; // Entries served (frm this list) so far this interval
  25. ULONG PrevEntriesServed; // Entries served during last interval
  26. #if DBG
  27. ULONG TotalServed; // Used for tracking backing list serv rate by the tracing code
  28. #endif
  29. } PER_PROC_SLISTS, *PPER_PROC_SLISTS;
  30. C_ASSERT(sizeof(PER_PROC_SLISTS) % UL_CACHE_LINE == 0);
  31. C_ASSERT(TYPE_ALIGNMENT(PER_PROC_SLISTS) == UL_CACHE_LINE);
  32. #define UL_MAX_SLIST_DEPTH (0xfffe)
  33. #define PER_PROC_SLIST(PoolHandle, Index) ((PPER_PROC_SLISTS) (PoolHandle) + Index)
  34. #define BACKING_SLIST(PoolHandle) PER_PROC_SLIST((PoolHandle), g_UlNumberOfProcessors)
  35. HANDLE
  36. PplCreatePool(
  37. IN PALLOCATE_FUNCTION Allocate,
  38. IN PFREE_FUNCTION Free,
  39. IN ULONG Flags,
  40. IN SIZE_T Size,
  41. IN ULONG Tag,
  42. IN USHORT Depth
  43. );
  44. VOID
  45. PplDestroyPool(
  46. IN HANDLE PoolHandle,
  47. IN ULONG Tag
  48. );
  49. __inline
  50. PVOID
  51. PplAllocate(
  52. IN HANDLE PoolHandle
  53. )
  54. {
  55. PUL_NPAGED_LOOKASIDE_LIST Lookaside;
  56. PVOID Entry;
  57. if (1 == g_UlNumberOfProcessors)
  58. {
  59. goto SingleProcessorCaseOrMissedPerProcessor;
  60. }
  61. // Try first for the per-processor lookaside list.
  62. //
  63. Lookaside = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle +
  64. KeGetCurrentProcessorNumber() + 1;
  65. Lookaside->List.L.TotalAllocates += 1;
  66. Entry = InterlockedPopEntrySList(&Lookaside->List.L.ListHead);
  67. if (!Entry)
  68. {
  69. Lookaside->List.L.AllocateMisses += 1;
  70. SingleProcessorCaseOrMissedPerProcessor:
  71. // We missed on the per-processor lookaside list, (or we're
  72. // running on a single processor machine) so try for
  73. // the overflow lookaside list.
  74. //
  75. Lookaside = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle;
  76. Lookaside->List.L.TotalAllocates += 1;
  77. Entry = InterlockedPopEntrySList(&Lookaside->List.L.ListHead);
  78. if (!Entry)
  79. {
  80. Lookaside->List.L.AllocateMisses += 1;
  81. Entry = (Lookaside->List.L.Allocate)(
  82. Lookaside->List.L.Type,
  83. Lookaside->List.L.Size,
  84. Lookaside->List.L.Tag);
  85. }
  86. }
  87. return Entry;
  88. }
  89. __inline
  90. VOID
  91. PplFree(
  92. IN HANDLE PoolHandle,
  93. IN PVOID Entry
  94. )
  95. {
  96. PUL_NPAGED_LOOKASIDE_LIST Lookaside;
  97. if (1 == g_UlNumberOfProcessors)
  98. {
  99. goto SingleProcessorCaseOrMissedPerProcessor;
  100. }
  101. // Try first for the per-processor lookaside list.
  102. //
  103. Lookaside = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle +
  104. KeGetCurrentProcessorNumber() + 1;
  105. Lookaside->List.L.TotalFrees += 1;
  106. if (ExQueryDepthSList(&Lookaside->List.L.ListHead) >=
  107. Lookaside->List.L.Depth)
  108. {
  109. Lookaside->List.L.FreeMisses += 1;
  110. SingleProcessorCaseOrMissedPerProcessor:
  111. // We missed on the per-processor lookaside list, (or we're
  112. // running on a single processor machine) so try for
  113. // the overflow lookaside list.
  114. //
  115. Lookaside = (PUL_NPAGED_LOOKASIDE_LIST)PoolHandle;
  116. Lookaside->List.L.TotalFrees += 1;
  117. if (ExQueryDepthSList(&Lookaside->List.L.ListHead) >=
  118. Lookaside->List.L.Depth)
  119. {
  120. Lookaside->List.L.FreeMisses += 1;
  121. (Lookaside->List.L.Free)(Entry);
  122. }
  123. else
  124. {
  125. InterlockedPushEntrySList(
  126. &Lookaside->List.L.ListHead,
  127. (PSLIST_ENTRY)Entry);
  128. }
  129. }
  130. else
  131. {
  132. InterlockedPushEntrySList(
  133. &Lookaside->List.L.ListHead,
  134. (PSLIST_ENTRY)Entry);
  135. }
  136. }
  137. HANDLE
  138. PpslCreatePool(
  139. IN ULONG Tag,
  140. IN USHORT MaxDepth,
  141. IN USHORT MinDepth
  142. );
  143. VOID
  144. PpslDestroyPool(
  145. IN HANDLE PoolHandle,
  146. IN ULONG Tag
  147. );
  148. __inline
  149. PSLIST_ENTRY
  150. PpslAllocate(
  151. IN HANDLE PoolHandle
  152. )
  153. {
  154. PSLIST_ENTRY Entry;
  155. PPER_PROC_SLISTS PPSList;
  156. PPSList = PER_PROC_SLIST(PoolHandle, KeGetCurrentProcessorNumber());
  157. Entry = InterlockedPopEntrySList(&(PPSList->SL));
  158. if (!Entry)
  159. {
  160. PPSList = BACKING_SLIST(PoolHandle);
  161. Entry = InterlockedPopEntrySList(&(PPSList->SL));
  162. }
  163. if (Entry)
  164. {
  165. InterlockedIncrement((PLONG) &PPSList->EntriesServed);
  166. #if DBG
  167. InterlockedIncrement((PLONG) &PPSList->TotalServed);
  168. #endif
  169. }
  170. return Entry;
  171. }
  172. __inline
  173. PSLIST_ENTRY
  174. PpslAllocateToTrim(
  175. IN HANDLE PoolHandle,
  176. IN ULONG Processor
  177. )
  178. {
  179. PSLIST_ENTRY Entry;
  180. PPER_PROC_SLISTS PPSList;
  181. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  182. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  183. if (ExQueryDepthSList(&(PPSList->SL)) > PPSList->MinDepth)
  184. {
  185. Entry = InterlockedPopEntrySList(&(PPSList->SL));
  186. }
  187. else
  188. {
  189. Entry = NULL;
  190. }
  191. return Entry;
  192. }
  193. __inline
  194. PSLIST_ENTRY
  195. PpslAllocateToDrain(
  196. IN HANDLE PoolHandle
  197. )
  198. {
  199. PSLIST_ENTRY Entry = NULL;
  200. PPER_PROC_SLISTS PPSList;
  201. CLONG NumberSLists;
  202. CLONG i;
  203. NumberSLists = g_UlNumberOfProcessors + 1;
  204. for (i = 0; i < NumberSLists; i++)
  205. {
  206. PPSList = PER_PROC_SLIST(PoolHandle, i);
  207. Entry = InterlockedPopEntrySList(&(PPSList->SL));
  208. if (Entry) {
  209. break;
  210. }
  211. }
  212. return Entry;
  213. }
  214. __inline
  215. BOOLEAN
  216. PpslFree(
  217. IN HANDLE PoolHandle,
  218. IN PVOID Entry
  219. )
  220. {
  221. PPER_PROC_SLISTS PPSList;
  222. BOOLEAN Freed = TRUE;
  223. PPSList = PER_PROC_SLIST(PoolHandle, KeGetCurrentProcessorNumber());
  224. if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth &&
  225. PPSList->Delta >= 0)
  226. {
  227. InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
  228. }
  229. else
  230. {
  231. PPSList = BACKING_SLIST(PoolHandle);
  232. if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth &&
  233. PPSList->Delta >= 0)
  234. {
  235. InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
  236. }
  237. else
  238. {
  239. Freed = FALSE;
  240. }
  241. }
  242. return Freed;
  243. }
  244. __inline
  245. BOOLEAN
  246. PpslFreeSpecifyList(
  247. IN HANDLE PoolHandle,
  248. IN PVOID Entry,
  249. IN ULONG Processor
  250. )
  251. {
  252. PPER_PROC_SLISTS PPSList;
  253. BOOLEAN Freed = TRUE;
  254. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  255. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  256. if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth)
  257. {
  258. InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
  259. }
  260. else
  261. {
  262. PPSList = BACKING_SLIST(PoolHandle);
  263. if (ExQueryDepthSList(&(PPSList->SL)) < PPSList->MaxDepth)
  264. {
  265. InterlockedPushEntrySList(&(PPSList->SL), (PSLIST_ENTRY)Entry);
  266. }
  267. else
  268. {
  269. Freed = FALSE;
  270. }
  271. }
  272. return Freed;
  273. }
  274. __inline
  275. USHORT
  276. PpslQueryBackingListDepth(
  277. IN HANDLE PoolHandle
  278. )
  279. {
  280. USHORT Depth;
  281. PPER_PROC_SLISTS PPSList;
  282. PPSList = BACKING_SLIST(PoolHandle);
  283. Depth = ExQueryDepthSList(&(PPSList->SL));
  284. return (Depth);
  285. }
  286. __inline
  287. USHORT
  288. PpslQueryDepth(
  289. IN HANDLE PoolHandle,
  290. IN ULONG Processor
  291. )
  292. {
  293. USHORT Depth;
  294. PPER_PROC_SLISTS PPSList;
  295. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  296. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  297. Depth = ExQueryDepthSList(&(PPSList->SL));
  298. return (Depth);
  299. }
  300. __inline
  301. USHORT
  302. PpslQueryMinDepth(
  303. IN HANDLE PoolHandle,
  304. IN ULONG Processor
  305. )
  306. {
  307. PPER_PROC_SLISTS PPSList;
  308. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  309. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  310. return PPSList->MinDepth;
  311. }
  312. __inline
  313. USHORT
  314. PpslQueryBackingListMinDepth(
  315. IN HANDLE PoolHandle
  316. )
  317. {
  318. PPER_PROC_SLISTS PPSList;
  319. PPSList = BACKING_SLIST(PoolHandle);
  320. return PPSList->MinDepth;
  321. }
  322. __inline
  323. LONG
  324. PpslAdjustActivityStats(
  325. IN HANDLE PoolHandle,
  326. IN ULONG Processor
  327. )
  328. {
  329. PPER_PROC_SLISTS PPSList;
  330. ULONG EntriesServed;
  331. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  332. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  333. EntriesServed =
  334. InterlockedExchange((PLONG) &PPSList->EntriesServed, 0);
  335. InterlockedExchange(
  336. &PPSList->Delta,
  337. EntriesServed - PPSList->PrevEntriesServed
  338. );
  339. PPSList->PrevEntriesServed = EntriesServed;
  340. return PPSList->Delta;
  341. }
  342. __inline
  343. ULONG
  344. PpslQueryPrevServed(
  345. IN HANDLE PoolHandle,
  346. IN ULONG Processor
  347. )
  348. {
  349. PPER_PROC_SLISTS PPSList;
  350. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  351. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  352. return PPSList->PrevEntriesServed;
  353. }
  354. #if DBG
  355. __inline
  356. LONG
  357. PpslQueryDelta(
  358. IN HANDLE PoolHandle,
  359. IN ULONG Processor
  360. )
  361. {
  362. PPER_PROC_SLISTS PPSList;
  363. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  364. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  365. return PPSList->Delta;
  366. }
  367. __inline
  368. ULONG
  369. PpslQueryTotalServed(
  370. IN HANDLE PoolHandle
  371. )
  372. {
  373. PPER_PROC_SLISTS PPSList;
  374. PPSList = BACKING_SLIST(PoolHandle);
  375. return PPSList->TotalServed;
  376. }
  377. __inline
  378. ULONG
  379. PpslQueryServed(
  380. IN HANDLE PoolHandle,
  381. IN ULONG Processor
  382. )
  383. {
  384. PPER_PROC_SLISTS PPSList;
  385. ASSERT(Processor <= (ULONG)g_UlNumberOfProcessors);
  386. PPSList = PER_PROC_SLIST(PoolHandle, Processor);
  387. return PPSList->EntriesServed;
  388. }
  389. #endif // DBG
  390. #endif // _PPLASL_H_