00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "exp.h"
00022
00023
00024
00025
00026
00027 #define MAXIMUM_SCAN_PERIOD 4
00028
00029
00030
00031
00032
00033 #define MINIMUM_LOOKASIDE_DEPTH 4
00034
00035
00036
00037
00038
00039 #define MINIMUM_ALLOCATION_THRESHOLD 25
00040
00041
00042
00043
00044
00045 LOGICAL
00046
ExpComputeLookasideDepth (
00047 IN ULONG Allocates,
00048 IN ULONG Misses,
00049 IN USHORT MaximumDepth,
00050 IN OUT PUSHORT Depth
00051 );
00052
00053 PVOID
00054
ExpDummyAllocate (
00055 IN POOL_TYPE PoolType,
00056 IN SIZE_T NumberOfBytes,
00057 IN ULONG Tag
00058 );
00059
00060 LOGICAL
00061
ExpScanGeneralLookasideList (
00062 IN PLIST_ENTRY ListHead,
00063 IN PKSPIN_LOCK SpinLock
00064 );
00065
00066 LOGICAL
00067
ExpScanPoolLookasideList (
00068 IN PLIST_ENTRY ListHead
00069 );
00070
00071
00072
00073
00074
00075 LIST_ENTRY
ExNPagedLookasideListHead;
00076 KSPIN_LOCK
ExNPagedLookasideLock;
00077 LIST_ENTRY
ExPagedLookasideListHead;
00078 KSPIN_LOCK
ExPagedLookasideLock;
00079 LIST_ENTRY
ExPoolLookasideListHead;
00080
00081
00082
00083
00084
00085 ULONG
ExpAdjustScanPeriod = 1;
00086 ULONG
ExpCurrentScanPeriod = 1;
00087
00088
VOID
00089 ExAdjustLookasideDepth (
00090 VOID
00091 )
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110 {
00111
00112 LOGICAL Changes;
00113
00114
00115
00116
00117
00118
00119
ExpCurrentScanPeriod -= 1;
00120
if (
ExpCurrentScanPeriod == 0) {
00121 Changes =
FALSE;
00122
00123
00124
00125
00126
00127 Changes |=
ExpScanGeneralLookasideList(&
ExNPagedLookasideListHead,
00128 &
ExNPagedLookasideLock);
00129
00130 Changes |=
ExpScanGeneralLookasideList(&
ExPagedLookasideListHead,
00131 &
ExPagedLookasideLock);
00132
00133
00134
00135
00136
00137 Changes |=
ExpScanPoolLookasideList(&
ExPoolLookasideListHead);
00138
00139
00140
00141
00142
00143
00144
00145
if (Changes !=
FALSE) {
00146
ExpAdjustScanPeriod = 1;
00147
00148 }
else {
00149
if (
ExpAdjustScanPeriod !=
MAXIMUM_SCAN_PERIOD) {
00150
ExpAdjustScanPeriod += 1;
00151 }
00152 }
00153
00154
ExpCurrentScanPeriod =
ExpAdjustScanPeriod;
00155 }
00156
00157
return;
00158 }
00159
00160 LOGICAL
00161 ExpComputeLookasideDepth (
00162 IN ULONG Allocates,
00163 IN ULONG Misses,
00164 IN USHORT MaximumDepth,
00165 IN OUT PUSHORT Depth
00166 )
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 {
00199
00200 LOGICAL Changes;
00201 ULONG Ratio;
00202 ULONG Target;
00203
00204
00205
00206
00207
00208
00209
00210
00211 Changes =
FALSE;
00212
if (Misses >= Allocates) {
00213 Misses = Allocates;
00214 }
00215
00216
if (Allocates == 0) {
00217 Allocates = 1;
00218 }
00219
00220 Ratio = (Misses * 1000) / Allocates;
00221 Target = *Depth;
00222
if ((Allocates /
ExpAdjustScanPeriod) <
MINIMUM_ALLOCATION_THRESHOLD) {
00223
if (Target > (
MINIMUM_LOOKASIDE_DEPTH + 10)) {
00224 Target -= 10;
00225
00226 }
else {
00227 Target =
MINIMUM_LOOKASIDE_DEPTH;
00228 }
00229
00230 }
else if (Ratio < 5) {
00231
if (Target > (
MINIMUM_LOOKASIDE_DEPTH + 1)) {
00232 Target -= 1;
00233
00234 }
else {
00235 Target =
MINIMUM_LOOKASIDE_DEPTH;
00236 }
00237
00238 }
else {
00239 Changes =
TRUE;
00240 Target += ((Ratio * MaximumDepth) / (1000 * 2)) + 5;
00241
if (Target > MaximumDepth) {
00242 Target = MaximumDepth;
00243 }
00244 }
00245
00246 *Depth = (
USHORT)Target;
00247
return Changes;
00248 }
00249
00250 LOGICAL
00251 ExpScanGeneralLookasideList (
00252 IN PLIST_ENTRY ListHead,
00253 IN PKSPIN_LOCK SpinLock
00254 )
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278 {
00279
00280 ULONG Allocates;
00281 LOGICAL Changes;
00282 PLIST_ENTRY Entry;
00283
PPAGED_LOOKASIDE_LIST Lookaside;
00284 ULONG Misses;
00285 KIRQL OldIrql;
00286
00287
00288
00289
00290
00291 Changes =
FALSE;
00292 ExAcquireSpinLock(SpinLock, &OldIrql);
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303 Entry = ListHead->Flink;
00304
while (Entry != ListHead) {
00305 Lookaside = CONTAINING_RECORD(Entry,
00306
PAGED_LOOKASIDE_LIST,
00307
L.ListEntry);
00308
00309
00310
00311
00312
00313
00314 Allocates = Lookaside->
L.
TotalAllocates - Lookaside->
L.
LastTotalAllocates;
00315 Lookaside->
L.
LastTotalAllocates = Lookaside->
L.
TotalAllocates;
00316 Misses = Lookaside->
L.
AllocateMisses - Lookaside->
L.
LastAllocateMisses;
00317 Lookaside->
L.
LastAllocateMisses = Lookaside->
L.
AllocateMisses;
00318
00319
00320
00321
00322
00323 Changes |=
ExpComputeLookasideDepth(Allocates,
00324 Misses,
00325 Lookaside->
L.
MaximumDepth,
00326 &Lookaside->
L.
Depth);
00327
00328 Entry = Entry->Flink;
00329 }
00330
00331
00332
00333
00334
00335 ExReleaseSpinLock(SpinLock, OldIrql);
00336
return Changes;
00337 }
00338
00339 LOGICAL
00340 ExpScanPoolLookasideList (
00341 IN PLIST_ENTRY ListHead
00342 )
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 {
00363
00364 ULONG Allocates;
00365 LOGICAL Changes;
00366
PNPAGED_LOOKASIDE_LIST Lookaside;
00367 PLIST_ENTRY NextEntry;
00368 ULONG Misses;
00369
00370
00371
00372
00373
00374
00375 Changes =
FALSE;
00376 NextEntry = ListHead->Flink;
00377
while (NextEntry != ListHead) {
00378 Lookaside = CONTAINING_RECORD(NextEntry,
00379
NPAGED_LOOKASIDE_LIST,
00380
L.ListEntry);
00381
00382
00383
00384
00385
00386
00387 Allocates = Lookaside->
L.
TotalAllocates - Lookaside->
L.
LastTotalAllocates;
00388 Lookaside->
L.
LastTotalAllocates = Lookaside->
L.
TotalAllocates;
00389 Misses = Allocates - (Lookaside->
L.
AllocateHits - Lookaside->
L.
LastAllocateHits);
00390 Lookaside->
L.
LastAllocateHits = Lookaside->
L.
AllocateHits;
00391
00392
00393
00394
00395
00396 Changes |=
ExpComputeLookasideDepth(Allocates,
00397 Misses,
00398 Lookaside->
L.
MaximumDepth,
00399 &Lookaside->
L.
Depth);
00400
00401 NextEntry = NextEntry->Flink;
00402 }
00403
00404
return Changes;
00405 }
00406
00407
VOID
00408 ExInitializeNPagedLookasideList (
00409 IN
PNPAGED_LOOKASIDE_LIST Lookaside,
00410 IN PALLOCATE_FUNCTION Allocate,
00411 IN PFREE_FUNCTION Free,
00412 IN ULONG Flags,
00413 IN SIZE_T Size,
00414 IN ULONG Tag,
00415 IN USHORT Depth
00416 )
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 {
00449
00450
00451
00452
00453
00454
ExInitializeSListHead(&Lookaside->L.ListHead);
00455 Lookaside->L.Depth =
MINIMUM_LOOKASIDE_DEPTH;
00456 Lookaside->L.MaximumDepth = 256;
00457 Lookaside->L.TotalAllocates = 0;
00458 Lookaside->L.AllocateMisses = 0;
00459 Lookaside->L.TotalFrees = 0;
00460 Lookaside->L.FreeMisses = 0;
00461 Lookaside->L.Type =
NonPagedPool | Flags;
00462 Lookaside->L.Tag = Tag;
00463 Lookaside->L.Size = (ULONG)
Size;
00464
if (Allocate ==
NULL) {
00465 Lookaside->L.Allocate =
ExAllocatePoolWithTag;
00466
00467 }
else {
00468 Lookaside->L.Allocate = Allocate;
00469 }
00470
00471
if (Free ==
NULL) {
00472 Lookaside->L.Free =
ExFreePool;
00473
00474 }
else {
00475 Lookaside->L.Free = Free;
00476 }
00477
00478 Lookaside->L.LastTotalAllocates = 0;
00479 Lookaside->L.LastAllocateMisses = 0;
00480
KeInitializeSpinLock(&Lookaside->Lock);
00481
00482
00483
00484
00485
00486
00487
ExInterlockedInsertTailList(&
ExNPagedLookasideListHead,
00488 &Lookaside->L.ListEntry,
00489 &
ExNPagedLookasideLock);
00490
return;
00491 }
00492
00493
VOID
00494 ExDeleteNPagedLookasideList (
00495 IN
PNPAGED_LOOKASIDE_LIST Lookaside
00496 )
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 {
00516
00517 PVOID Entry;
00518 KIRQL OldIrql;
00519
00520
00521
00522
00523
00524
00525 ExAcquireSpinLock(&
ExNPagedLookasideLock, &OldIrql);
00526 RemoveEntryList(&Lookaside->L.ListEntry);
00527 ExReleaseSpinLock(&
ExNPagedLookasideLock, OldIrql);
00528
00529
00530
00531
00532
00533
00534 Lookaside->L.Allocate =
ExpDummyAllocate;
00535
while ((Entry =
ExAllocateFromNPagedLookasideList(Lookaside)) !=
NULL) {
00536 (Lookaside->L.Free)(Entry);
00537 }
00538
00539
return;
00540 }
00541
00542
VOID
00543 ExInitializePagedLookasideList (
00544 IN
PPAGED_LOOKASIDE_LIST Lookaside,
00545 IN PALLOCATE_FUNCTION Allocate,
00546 IN PFREE_FUNCTION Free,
00547 IN ULONG Flags,
00548 IN SIZE_T Size,
00549 IN ULONG Tag,
00550 IN USHORT Depth
00551 )
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 {
00584
00585
00586
00587
00588
00589
ExInitializeSListHead(&Lookaside->L.ListHead);
00590 Lookaside->L.Depth =
MINIMUM_LOOKASIDE_DEPTH;
00591 Lookaside->L.MaximumDepth = 256;
00592 Lookaside->L.TotalAllocates = 0;
00593 Lookaside->L.AllocateMisses = 0;
00594 Lookaside->L.TotalFrees = 0;
00595 Lookaside->L.FreeMisses = 0;
00596 Lookaside->L.Type =
PagedPool | Flags;
00597 Lookaside->L.Tag = Tag;
00598 Lookaside->L.Size = (ULONG)
Size;
00599
if (Allocate ==
NULL) {
00600 Lookaside->L.Allocate =
ExAllocatePoolWithTag;
00601
00602 }
else {
00603 Lookaside->L.Allocate = Allocate;
00604 }
00605
00606
if (Free ==
NULL) {
00607 Lookaside->L.Free =
ExFreePool;
00608
00609 }
else {
00610 Lookaside->L.Free = Free;
00611 }
00612
00613 Lookaside->L.LastTotalAllocates = 0;
00614 Lookaside->L.LastAllocateMisses = 0;
00615
ExInitializeFastMutex(&Lookaside->Lock);
00616
00617
00618
00619
00620
00621
00622
ExInterlockedInsertTailList(&
ExPagedLookasideListHead,
00623 &Lookaside->L.ListEntry,
00624 &
ExPagedLookasideLock);
00625
return;
00626 }
00627
00628
VOID
00629 ExDeletePagedLookasideList (
00630 IN
PPAGED_LOOKASIDE_LIST Lookaside
00631 )
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650 {
00651
00652 PVOID Entry;
00653 KIRQL OldIrql;
00654
00655
00656
00657
00658
00659
00660 ExAcquireSpinLock(&
ExPagedLookasideLock, &OldIrql);
00661 RemoveEntryList(&Lookaside->L.ListEntry);
00662 ExReleaseSpinLock(&
ExPagedLookasideLock, OldIrql);
00663
00664
00665
00666
00667
00668
00669 Lookaside->L.Allocate =
ExpDummyAllocate;
00670
while ((Entry =
ExAllocateFromPagedLookasideList(Lookaside)) !=
NULL) {
00671 (Lookaside->L.Free)(Entry);
00672 }
00673
00674
return;
00675 }
00676
00677
#if !defined(_MIPS_) && !defined(_ALPHA_) && !defined(_IA64_)
00678
00679
00680 PVOID
00681 ExAllocateFromPagedLookasideList(
00682 IN
PPAGED_LOOKASIDE_LIST Lookaside
00683 )
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704 {
00705
00706 PVOID Entry;
00707
00708 Lookaside->L.TotalAllocates += 1;
00709
00710
if (
Isx86FeaturePresent(
KF_CMPXCHG8B)) {
00711
if ((Entry =
ExInterlockedPopEntrySList(&Lookaside->L.ListHead,
00712
NULL)) ==
NULL) {
00713
00714 Lookaside->L.AllocateMisses += 1;
00715 Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
00716 Lookaside->L.Size,
00717 Lookaside->L.Tag);
00718 }
00719
00720
return Entry;
00721 }
00722
00723 ExAcquireFastMutex(&Lookaside->Lock);
00724 Entry = PopEntryList(&Lookaside->L.ListHead.Next);
00725
if (Entry ==
NULL) {
00726 ExReleaseFastMutex(&Lookaside->Lock);
00727 Lookaside->L.AllocateMisses += 1;
00728 Entry = (Lookaside->L.Allocate)(Lookaside->L.Type,
00729 Lookaside->L.Size,
00730 Lookaside->L.Tag);
00731
00732 }
else {
00733 Lookaside->L.ListHead.Depth -= 1;
00734 ExReleaseFastMutex(&Lookaside->Lock);
00735 }
00736
00737
return Entry;
00738 }
00739
00740
VOID
00741 ExFreeToPagedLookasideList(
00742 IN
PPAGED_LOOKASIDE_LIST Lookaside,
00743 IN PVOID Entry
00744 )
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766 {
00767
00768 Lookaside->L.TotalFrees += 1;
00769
00770
if (
Isx86FeaturePresent(
KF_CMPXCHG8B)) {
00771
if (
ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
00772 Lookaside->L.FreeMisses += 1;
00773 (Lookaside->L.Free)(Entry);
00774
00775 }
else {
00776
ExInterlockedPushEntrySList(&Lookaside->L.ListHead,
00777 (PSINGLE_LIST_ENTRY)Entry,
00778
NULL);
00779 }
00780
00781
return;
00782 }
00783
00784 ExAcquireFastMutex(&Lookaside->Lock);
00785
if (
ExQueryDepthSList(&Lookaside->L.ListHead) >= Lookaside->L.Depth) {
00786 ExReleaseFastMutex(&Lookaside->Lock);
00787 Lookaside->L.FreeMisses += 1;
00788 (Lookaside->L.Free)(Entry);
00789
00790 }
else {
00791 PushEntryList(&Lookaside->L.ListHead.Next, (PSINGLE_LIST_ENTRY)Entry);
00792 Lookaside->L.ListHead.Depth += 1;
00793 ExReleaseFastMutex(&Lookaside->Lock);
00794 }
00795
00796
return;
00797 }
00798
00799
#endif
00800
00801 PVOID
00802 ExpDummyAllocate (
00803 IN POOL_TYPE PoolType,
00804 IN SIZE_T NumberOfBytes,
00805 IN ULONG Tag
00806 )
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829 {
00830
00831
return NULL;
00832 }