1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/ex/lookas.c 5 * PURPOSE: Lookaside Lists 6 * PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org) 7 */ 8 9 /* INCLUDES ******************************************************************/ 10 11 #include <ntoskrnl.h> 12 #define NDEBUG 13 #include <debug.h> 14 15 /* GLOBALS *******************************************************************/ 16 17 LIST_ENTRY ExpNonPagedLookasideListHead; 18 KSPIN_LOCK ExpNonPagedLookasideListLock; 19 LIST_ENTRY ExpPagedLookasideListHead; 20 KSPIN_LOCK ExpPagedLookasideListLock; 21 LIST_ENTRY ExSystemLookasideListHead; 22 LIST_ENTRY ExPoolLookasideListHead; 23 GENERAL_LOOKASIDE ExpSmallNPagedPoolLookasideLists[MAXIMUM_PROCESSORS]; 24 GENERAL_LOOKASIDE ExpSmallPagedPoolLookasideLists[MAXIMUM_PROCESSORS]; 25 26 /* PRIVATE FUNCTIONS *********************************************************/ 27 28 CODE_SEG("INIT") 29 VOID 30 NTAPI 31 ExInitializeSystemLookasideList(IN PGENERAL_LOOKASIDE List, 32 IN POOL_TYPE Type, 33 IN ULONG Size, 34 IN ULONG Tag, 35 IN USHORT MaximumDepth, 36 IN PLIST_ENTRY ListHead) 37 { 38 /* Initialize the list */ 39 List->Tag = Tag; 40 List->Type = Type; 41 List->Size = Size; 42 InsertHeadList(ListHead, &List->ListEntry); 43 List->MaximumDepth = MaximumDepth; 44 List->Depth = 2; 45 List->Allocate = ExAllocatePoolWithTag; 46 List->Free = ExFreePool; 47 InitializeSListHead(&List->ListHead); 48 List->TotalAllocates = 0; 49 List->AllocateHits = 0; 50 List->TotalFrees = 0; 51 List->FreeHits = 0; 52 List->LastTotalAllocates = 0; 53 List->LastAllocateHits = 0; 54 } 55 56 CODE_SEG("INIT") 57 VOID 58 NTAPI 59 ExInitPoolLookasidePointers(VOID) 60 { 61 ULONG i; 62 PKPRCB Prcb = KeGetCurrentPrcb(); 63 PGENERAL_LOOKASIDE Entry; 64 65 /* Loop for all pool lists */ 66 for (i = 0; i < NUMBER_POOL_LOOKASIDE_LISTS; i++) 67 { 68 /* Initialize the non-paged list */ 69 Entry = &ExpSmallNPagedPoolLookasideLists[i]; 70 InitializeSListHead(&Entry->ListHead); 71 72 /* Bind to PRCB */ 73 Prcb->PPNPagedLookasideList[i].P = Entry; 74 Prcb->PPNPagedLookasideList[i].L = Entry; 75 76 /* Initialize the paged list */ 77 Entry = &ExpSmallPagedPoolLookasideLists[i]; 78 InitializeSListHead(&Entry->ListHead); 79 80 /* Bind to PRCB */ 81 Prcb->PPPagedLookasideList[i].P = Entry; 82 Prcb->PPPagedLookasideList[i].L = Entry; 83 } 84 } 85 86 CODE_SEG("INIT") 87 VOID 88 NTAPI 89 ExpInitLookasideLists(VOID) 90 { 91 ULONG i; 92 93 /* Initialize locks and lists */ 94 InitializeListHead(&ExpNonPagedLookasideListHead); 95 InitializeListHead(&ExpPagedLookasideListHead); 96 InitializeListHead(&ExSystemLookasideListHead); 97 InitializeListHead(&ExPoolLookasideListHead); 98 KeInitializeSpinLock(&ExpNonPagedLookasideListLock); 99 KeInitializeSpinLock(&ExpPagedLookasideListLock); 100 101 /* Initialize the system lookaside lists */ 102 for (i = 0; i < MAXIMUM_PROCESSORS; i++) 103 { 104 /* Initialize the non-paged list */ 105 ExInitializeSystemLookasideList(&ExpSmallNPagedPoolLookasideLists[i], 106 NonPagedPool, 107 (i + 1) * 8, 108 'looP', 109 256, 110 &ExPoolLookasideListHead); 111 112 /* Initialize the paged list */ 113 ExInitializeSystemLookasideList(&ExpSmallPagedPoolLookasideLists[i], 114 PagedPool, 115 (i + 1) * 8, 116 'looP', 117 256, 118 &ExPoolLookasideListHead); 119 } 120 } 121 122 /* PUBLIC FUNCTIONS **********************************************************/ 123 124 /* 125 * @implemented 126 */ 127 PVOID 128 NTAPI 129 ExiAllocateFromPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside) 130 { 131 PVOID Entry; 132 133 Lookaside->L.TotalAllocates++; 134 Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead); 135 if (!Entry) 136 { 137 Lookaside->L.AllocateMisses++; 138 Entry = (Lookaside->L.Allocate)(Lookaside->L.Type, 139 Lookaside->L.Size, 140 Lookaside->L.Tag); 141 } 142 return Entry; 143 } 144 145 /* 146 * @implemented 147 */ 148 VOID 149 NTAPI 150 ExiFreeToPagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside, 151 IN PVOID Entry) 152 { 153 Lookaside->L.TotalFrees++; 154 if (ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) 155 { 156 Lookaside->L.FreeMisses++; 157 (Lookaside->L.Free)(Entry); 158 } 159 else 160 { 161 InterlockedPushEntrySList(&Lookaside->L.ListHead, (PSLIST_ENTRY)Entry); 162 } 163 } 164 165 /* 166 * @implemented 167 */ 168 VOID 169 NTAPI 170 ExDeleteNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside) 171 { 172 KIRQL OldIrql; 173 PVOID Entry; 174 175 /* Pop all entries off the stack and release their resources */ 176 for (;;) 177 { 178 Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead); 179 if (!Entry) break; 180 (*Lookaside->L.Free)(Entry); 181 } 182 183 /* Remove from list */ 184 KeAcquireSpinLock(&ExpNonPagedLookasideListLock, &OldIrql); 185 RemoveEntryList(&Lookaside->L.ListEntry); 186 KeReleaseSpinLock(&ExpNonPagedLookasideListLock, OldIrql); 187 } 188 189 /* 190 * @implemented 191 */ 192 VOID 193 NTAPI 194 ExDeletePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside) 195 { 196 KIRQL OldIrql; 197 PVOID Entry; 198 199 /* Pop all entries off the stack and release their resources */ 200 for (;;) 201 { 202 Entry = InterlockedPopEntrySList(&Lookaside->L.ListHead); 203 if (!Entry) break; 204 (*Lookaside->L.Free)(Entry); 205 } 206 207 /* Remove from list */ 208 KeAcquireSpinLock(&ExpPagedLookasideListLock, &OldIrql); 209 RemoveEntryList(&Lookaside->L.ListEntry); 210 KeReleaseSpinLock(&ExpPagedLookasideListLock, OldIrql); 211 } 212 213 /* 214 * @implemented 215 */ 216 VOID 217 NTAPI 218 ExInitializeNPagedLookasideList(IN PNPAGED_LOOKASIDE_LIST Lookaside, 219 IN PALLOCATE_FUNCTION Allocate OPTIONAL, 220 IN PFREE_FUNCTION Free OPTIONAL, 221 IN ULONG Flags, 222 IN SIZE_T Size, 223 IN ULONG Tag, 224 IN USHORT Depth) 225 { 226 /* Initialize the Header */ 227 ExInitializeSListHead(&Lookaside->L.ListHead); 228 Lookaside->L.TotalAllocates = 0; 229 Lookaside->L.AllocateMisses = 0; 230 Lookaside->L.TotalFrees = 0; 231 Lookaside->L.FreeMisses = 0; 232 Lookaside->L.Type = NonPagedPool | Flags; 233 Lookaside->L.Tag = Tag; 234 Lookaside->L.Size = (ULONG)Size; 235 Lookaside->L.Depth = 4; 236 Lookaside->L.MaximumDepth = 256; 237 Lookaside->L.LastTotalAllocates = 0; 238 Lookaside->L.LastAllocateMisses = 0; 239 240 /* Set the Allocate/Free Routines */ 241 if (Allocate) 242 { 243 Lookaside->L.Allocate = Allocate; 244 } 245 else 246 { 247 Lookaside->L.Allocate = ExAllocatePoolWithTag; 248 } 249 250 if (Free) 251 { 252 Lookaside->L.Free = Free; 253 } 254 else 255 { 256 Lookaside->L.Free = ExFreePool; 257 } 258 259 /* Insert it into the list */ 260 ExInterlockedInsertTailList(&ExpNonPagedLookasideListHead, 261 &Lookaside->L.ListEntry, 262 &ExpNonPagedLookasideListLock); 263 } 264 265 /* 266 * @implemented 267 */ 268 VOID 269 NTAPI 270 ExInitializePagedLookasideList(IN PPAGED_LOOKASIDE_LIST Lookaside, 271 IN PALLOCATE_FUNCTION Allocate OPTIONAL, 272 IN PFREE_FUNCTION Free OPTIONAL, 273 IN ULONG Flags, 274 IN SIZE_T Size, 275 IN ULONG Tag, 276 IN USHORT Depth) 277 { 278 /* Initialize the Header */ 279 ExInitializeSListHead(&Lookaside->L.ListHead); 280 Lookaside->L.TotalAllocates = 0; 281 Lookaside->L.AllocateMisses = 0; 282 Lookaside->L.TotalFrees = 0; 283 Lookaside->L.FreeMisses = 0; 284 Lookaside->L.Type = PagedPool | Flags; 285 Lookaside->L.Tag = Tag; 286 Lookaside->L.Size = (ULONG)Size; 287 Lookaside->L.Depth = 4; 288 Lookaside->L.MaximumDepth = 256; 289 Lookaside->L.LastTotalAllocates = 0; 290 Lookaside->L.LastAllocateMisses = 0; 291 292 /* Set the Allocate/Free Routines */ 293 if (Allocate) 294 { 295 Lookaside->L.Allocate = Allocate; 296 } 297 else 298 { 299 Lookaside->L.Allocate = ExAllocatePoolWithTag; 300 } 301 302 if (Free) 303 { 304 Lookaside->L.Free = Free; 305 } 306 else 307 { 308 Lookaside->L.Free = ExFreePool; 309 } 310 311 /* Insert it into the list */ 312 ExInterlockedInsertTailList(&ExpPagedLookasideListHead, 313 &Lookaside->L.ListEntry, 314 &ExpPagedLookasideListLock); 315 } 316 317 /* EOF */ 318