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