Reactos

NTOS:CC Free some VACBs when we're under memory pressure

authored by

Jérôme Gardou and committed by
Timo Kreuzer
69daff72 470ad188

+44 -58
+10
ntoskrnl/cc/lazywrite.c
··· 130 130 ++CcLazyWriteIos; 131 131 DPRINT("Lazy writer done (%d)\n", Count); 132 132 } 133 + 134 + /* Make sure we're not throttling writes after this */ 135 + while (MmAvailablePages < MmThrottleTop) 136 + { 137 + /* Break if we can't even find one to free */ 138 + if (!CcRosFreeOneUnusedVacb()) 139 + { 140 + break; 141 + } 142 + } 133 143 } 134 144 135 145 VOID
+30 -58
ntoskrnl/cc/view.c
··· 595 595 } 596 596 } 597 597 598 - static 599 598 BOOLEAN 600 - CcRosFreeUnusedVacb ( 601 - PULONG Count) 599 + CcRosFreeOneUnusedVacb( 600 + VOID) 602 601 { 603 - ULONG cFreed; 604 - BOOLEAN Freed; 605 602 KIRQL oldIrql; 606 - PROS_VACB current; 607 - LIST_ENTRY FreeList; 608 603 PLIST_ENTRY current_entry; 609 - 610 - cFreed = 0; 611 - Freed = FALSE; 612 - InitializeListHead(&FreeList); 604 + PROS_VACB to_free = NULL; 613 605 614 606 oldIrql = KeAcquireQueuedSpinLock(LockQueueMasterLock); 615 607 616 608 /* Browse all the available VACB */ 617 609 current_entry = VacbLruListHead.Flink; 618 - while (current_entry != &VacbLruListHead) 610 + while ((current_entry != &VacbLruListHead) && (to_free == NULL)) 619 611 { 620 612 ULONG Refs; 613 + PROS_VACB current; 621 614 622 615 current = CONTAINING_RECORD(current_entry, 623 616 ROS_VACB, 624 617 VacbLruListEntry); 625 - current_entry = current_entry->Flink; 626 618 627 619 KeAcquireSpinLockAtDpcLevel(&current->SharedCacheMap->CacheMapLock); 628 620 ··· 634 626 ASSERT(!current->MappedCount); 635 627 ASSERT(Refs == 1); 636 628 637 - /* Reset and move to free list */ 629 + /* Reset it, this is the one we want to free */ 638 630 RemoveEntryList(&current->CacheMapVacbListEntry); 631 + InitializeListHead(&current->CacheMapVacbListEntry); 639 632 RemoveEntryList(&current->VacbLruListEntry); 640 633 InitializeListHead(&current->VacbLruListEntry); 641 - InsertHeadList(&FreeList, &current->CacheMapVacbListEntry); 634 + 635 + to_free = current; 642 636 } 643 637 644 638 KeReleaseSpinLockFromDpcLevel(&current->SharedCacheMap->CacheMapLock); 645 639 640 + current_entry = current_entry->Flink; 646 641 } 647 642 648 643 KeReleaseQueuedSpinLock(LockQueueMasterLock, oldIrql); 649 644 650 - /* And now, free any of the found VACB, that'll free memory! */ 651 - while (!IsListEmpty(&FreeList)) 652 - { 653 - ULONG Refs; 654 - 655 - current_entry = RemoveHeadList(&FreeList); 656 - current = CONTAINING_RECORD(current_entry, 657 - ROS_VACB, 658 - CacheMapVacbListEntry); 659 - InitializeListHead(&current->CacheMapVacbListEntry); 660 - Refs = CcRosVacbDecRefCount(current); 661 - ASSERT(Refs == 0); 662 - ++cFreed; 663 - } 664 - 665 - /* If we freed at least one VACB, return success */ 666 - if (cFreed != 0) 645 + /* And now, free the VACB that we found, if any. */ 646 + if (to_free == NULL) 667 647 { 668 - Freed = TRUE; 648 + return FALSE; 669 649 } 670 650 671 - /* If caller asked for free count, return it */ 672 - if (Count != NULL) 673 - { 674 - *Count = cFreed; 675 - } 651 + /* This must be its last ref */ 652 + NT_VERIFY(CcRosVacbDecRefCount(to_free) == 0); 676 653 677 - return Freed; 654 + return TRUE; 678 655 } 679 656 680 657 static ··· 690 667 NTSTATUS Status; 691 668 KIRQL oldIrql; 692 669 ULONG Refs; 693 - BOOLEAN Retried; 694 670 SIZE_T ViewSize = VACB_MAPPING_GRANULARITY; 695 671 696 672 ASSERT(SharedCacheMap); ··· 711 687 712 688 CcRosVacbIncRefCount(current); 713 689 714 - Retried = FALSE; 715 - Retry: 716 - /* Map VACB in system space */ 717 - Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, &current->BaseAddress, &ViewSize, &current->FileOffset, 0); 718 - 719 - if (!NT_SUCCESS(Status)) 690 + while (TRUE) 720 691 { 721 - ULONG Freed; 722 - /* If no space left, try to prune unused VACB 723 - * to recover space to map our VACB 724 - * If it succeed, retry to map, otherwise 725 - * just fail. 726 - */ 727 - if (!Retried && CcRosFreeUnusedVacb(&Freed)) 692 + /* Map VACB in system space */ 693 + Status = MmMapViewInSystemSpaceEx(SharedCacheMap->Section, &current->BaseAddress, &ViewSize, &current->FileOffset, 0); 694 + if (NT_SUCCESS(Status)) 728 695 { 729 - DPRINT("Prunned %d VACB, trying again\n", Freed); 730 - Retried = TRUE; 731 - goto Retry; 696 + break; 732 697 } 733 698 734 - ExFreeToNPagedLookasideList(&VacbLookasideList, current); 735 - return Status; 699 + /* 700 + * If no space left, try to prune one unused VACB to recover space to map our VACB. 701 + * If it succeeds, retry to map, otherwise just fail. 702 + */ 703 + if (!CcRosFreeOneUnusedVacb()) 704 + { 705 + ExFreeToNPagedLookasideList(&VacbLookasideList, current); 706 + return Status; 707 + } 736 708 } 737 709 738 710 #if DBG
+4
ntoskrnl/include/internal/cc.h
··· 509 509 } 510 510 #define CcRosVacbGetRefCount(vacb) InterlockedCompareExchange((PLONG)&(vacb)->ReferenceCount, 0, 0) 511 511 #endif 512 + 513 + BOOLEAN 514 + CcRosFreeOneUnusedVacb( 515 + VOID);