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.

240 lines
5.4 KiB

  1. /*++
  2. Copyright (c) 1999-2000 Microsoft Corporation
  3. Module Name:
  4. pplasl.c
  5. Abstract:
  6. This file contains the implementation of a per-processor lookaside
  7. list manager.
  8. Author:
  9. Shaun Cox (shaunco) 25-Oct-1999
  10. --*/
  11. #include "ntddk.h"
  12. #include "pplasl.h"
  13. HANDLE
  14. PplCreatePool(
  15. IN PALLOCATE_FUNCTION Allocate,
  16. IN PFREE_FUNCTION Free,
  17. IN ULONG Flags,
  18. IN SIZE_T Size,
  19. IN ULONG Tag,
  20. IN USHORT Depth
  21. )
  22. {
  23. HANDLE PoolHandle;
  24. SIZE_T PoolSize;
  25. CCHAR NumberProcessors;
  26. CCHAR NumberLookasideLists;
  27. CCHAR i;
  28. PNPAGED_LOOKASIDE_LIST Lookaside;
  29. #if MILLEN
  30. NumberProcessors = 1;
  31. #else // MILLEN
  32. NumberProcessors = KeNumberProcessors;
  33. #endif // !MILLEN
  34. // Allocate room for 1 lookaside list per processor plus 1 extra
  35. // lookaside list for overflow. Only allocate 1 lookaside list if
  36. // we're on a single processor machine.
  37. //
  38. NumberLookasideLists = NumberProcessors;
  39. if (NumberProcessors > 1)
  40. {
  41. NumberLookasideLists++;
  42. }
  43. PoolSize = sizeof(NPAGED_LOOKASIDE_LIST) * NumberLookasideLists;
  44. PoolHandle = ExAllocatePoolWithTagPriority(NonPagedPool, PoolSize, Tag,
  45. NormalPoolPriority);
  46. if (PoolHandle)
  47. {
  48. for (i = 0, Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
  49. i < NumberLookasideLists;
  50. i++, Lookaside++)
  51. {
  52. ExInitializeNPagedLookasideList(
  53. Lookaside,
  54. Allocate,
  55. Free,
  56. Flags,
  57. Size,
  58. Tag,
  59. Depth);
  60. // ExInitializeNPagedLookasideList doesn't really set the
  61. // maximum depth to Depth, so we'll do it here.
  62. //
  63. if (Depth != 0) {
  64. Lookaside->L.MaximumDepth = Depth;
  65. }
  66. }
  67. }
  68. return PoolHandle;
  69. }
  70. VOID
  71. PplDestroyPool(
  72. IN HANDLE PoolHandle
  73. )
  74. {
  75. CCHAR NumberProcessors;
  76. CCHAR NumberLookasideLists;
  77. CCHAR i;
  78. PNPAGED_LOOKASIDE_LIST Lookaside;
  79. if (!PoolHandle)
  80. {
  81. return;
  82. }
  83. #if MILLEN
  84. NumberProcessors = 1;
  85. #else // MILLEN
  86. NumberProcessors = KeNumberProcessors;
  87. #endif // !MILLEN
  88. NumberLookasideLists = NumberProcessors;
  89. if (NumberProcessors > 1)
  90. {
  91. NumberLookasideLists++;
  92. }
  93. for (i = 0, Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
  94. i < NumberLookasideLists;
  95. i++, Lookaside++)
  96. {
  97. ExDeleteNPagedLookasideList(Lookaside);
  98. }
  99. ExFreePool(PoolHandle);
  100. }
  101. PVOID
  102. PplAllocate(
  103. IN HANDLE PoolHandle,
  104. OUT LOGICAL *FromList
  105. )
  106. {
  107. PNPAGED_LOOKASIDE_LIST Lookaside;
  108. CCHAR NumberProcessors;
  109. PVOID Entry;
  110. // Assume we'll get the item from the lookaside list.
  111. //
  112. *FromList = TRUE;
  113. #if MILLEN
  114. NumberProcessors = 1;
  115. #else // MILLEN
  116. NumberProcessors = KeNumberProcessors;
  117. #endif // !MILLEN
  118. if (1 == NumberProcessors)
  119. {
  120. goto SingleProcessorCaseOrMissedPerProcessor;
  121. }
  122. // Try first for the per-processor lookaside list.
  123. //
  124. Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle +
  125. KeGetCurrentProcessorNumber() + 1;
  126. Lookaside->L.TotalAllocates += 1;
  127. Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
  128. if (!Entry)
  129. {
  130. Lookaside->L.AllocateMisses += 1;
  131. SingleProcessorCaseOrMissedPerProcessor:
  132. // We missed on the per-processor lookaside list, (or we're
  133. // running on a single processor machine) so try for
  134. // the overflow lookaside list.
  135. //
  136. Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
  137. Lookaside->L.TotalAllocates += 1;
  138. Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead);
  139. if (!Entry)
  140. {
  141. Lookaside->L.AllocateMisses += 1;
  142. Entry = (Lookaside->L.Allocate)(
  143. Lookaside->L.Type,
  144. Lookaside->L.Size,
  145. Lookaside->L.Tag);
  146. *FromList = FALSE;
  147. }
  148. }
  149. return Entry;
  150. }
  151. VOID
  152. PplFree(
  153. IN HANDLE PoolHandle,
  154. IN PVOID Entry
  155. )
  156. {
  157. PNPAGED_LOOKASIDE_LIST Lookaside;
  158. CCHAR NumberProcessors;
  159. #if MILLEN
  160. NumberProcessors = 1;
  161. #else // MILLEN
  162. NumberProcessors = KeNumberProcessors;
  163. #endif // !MILLEN
  164. if (1 == NumberProcessors)
  165. {
  166. goto SingleProcessorCaseOrMissedPerProcessor;
  167. }
  168. // Try first for the per-processor lookaside list.
  169. //
  170. Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle +
  171. KeGetCurrentProcessorNumber() + 1;
  172. Lookaside->L.TotalFrees += 1;
  173. if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth)
  174. {
  175. Lookaside->L.FreeMisses += 1;
  176. SingleProcessorCaseOrMissedPerProcessor:
  177. // We missed on the per-processor lookaside list, (or we're
  178. // running on a single processor machine) so try for
  179. // the overflow lookaside list.
  180. //
  181. Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle;
  182. Lookaside->L.TotalFrees += 1;
  183. if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth)
  184. {
  185. Lookaside->L.FreeMisses += 1;
  186. (Lookaside->L.Free)(Entry);
  187. }
  188. else
  189. {
  190. InterlockedPushEntrySList(
  191. &Lookaside->L.ListHead,
  192. (PSINGLE_LIST_ENTRY)Entry);
  193. }
  194. }
  195. else
  196. {
  197. InterlockedPushEntrySList(
  198. &Lookaside->L.ListHead,
  199. (PSINGLE_LIST_ENTRY)Entry);
  200. }
  201. }