[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / cc / view.c
index a453ecc..b8ce087 100644 (file)
@@ -189,6 +189,7 @@ CcRosFlushDirtyPages(ULONG Target, PULONG Count)
     
     (*Count) = 0;
     
+    KeEnterCriticalRegion();
     KeAcquireGuardedMutex(&ViewLock);
     
     WriteCount[0] = WriteCount[1];
@@ -278,6 +279,7 @@ CcRosFlushDirtyPages(ULONG Target, PULONG Count)
     }
     
     KeReleaseGuardedMutex(&ViewLock);
+    KeLeaveCriticalRegion();
     
     DPRINT("CcRosFlushDirtyPages() finished\n");
     return(STATUS_SUCCESS);
@@ -300,82 +302,80 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
     ULONG PagesFreed;
     KIRQL oldIrql;
     LIST_ENTRY FreeList;
-    
+    PFN_NUMBER Page;
+    ULONG i;
+
     DPRINT("CcRosTrimCache(Target %d)\n", Target);
+
+    InitializeListHead(&FreeList);
+
+    /* Flush dirty pages to disk */
+    CcRosFlushDirtyPages(Target, NrFreed);
     
+    if ((*NrFreed) != 0) DPRINT1("Flushed %d dirty cache pages to disk\n", (*NrFreed));
+
     *NrFreed = 0;
-    
-    InitializeListHead(&FreeList);
 
     KeAcquireGuardedMutex(&ViewLock);
+
     current_entry = CacheSegmentLRUListHead.Flink;
-    while (current_entry != &CacheSegmentLRUListHead && Target > 0)
+    while (current_entry != &CacheSegmentLRUListHead)
     {
-        NTSTATUS Status;
-        
-        Status = STATUS_SUCCESS;
         current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
                                     CacheSegmentLRUListEntry);
         current_entry = current_entry->Flink;
-        
+
         KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
 
-        if (current->MappedCount > 0 && !current->Dirty && !current->PageOut)
+        /* Reference the cache segment */
+        CcRosCacheSegmentIncRefCount(current);
+
+        /* Check if it's mapped and not dirty */
+        if (current->MappedCount > 0 && !current->Dirty)
         {
-            ULONG i;
-            
-            CcRosCacheSegmentIncRefCount(current);
-            current->PageOut = TRUE;
+            /* We have to break these locks because Cc sucks */
             KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
             KeReleaseGuardedMutex(&ViewLock);
+
+            /* Page out the segment */
             for (i = 0; i < current->Bcb->CacheSegmentSize / PAGE_SIZE; i++)
             {
-                PFN_TYPE Page;
-                Page = (PFN_TYPE)(MmGetPhysicalAddress((char*)current->BaseAddress + i * PAGE_SIZE).QuadPart >> PAGE_SHIFT);
-                Status = MmPageOutPhysicalAddress(Page);
+                Page = (PFN_NUMBER)(MmGetPhysicalAddress((PUCHAR)current->BaseAddress + (i * PAGE_SIZE)).QuadPart >> PAGE_SHIFT);
+
+                MmPageOutPhysicalAddress(Page);
             }
+
+            /* Reacquire the locks */
             KeAcquireGuardedMutex(&ViewLock);
             KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
-            CcRosCacheSegmentDecRefCount(current);
-        }
-        
-        if (current->ReferenceCount == 0)
-        {
-            PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
-            //            PagesFreed = PagesPerSegment;
-            PagesFreed = min(PagesPerSegment, Target);
-            Target -= PagesFreed;
-            (*NrFreed) += PagesFreed;            
         }
-        
-        KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
-    }
-    
-    current_entry = CacheSegmentLRUListHead.Flink;
-    while (current_entry != &CacheSegmentLRUListHead)
-    {
-        current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT,
-                                    CacheSegmentLRUListEntry);
-        current->PageOut = FALSE;
-        current_entry = current_entry->Flink;
-        
-        KeAcquireSpinLock(&current->Bcb->BcbLock, &oldIrql);
+
+        /* Dereference the cache segment */
+        CcRosCacheSegmentDecRefCount(current);
+
+        /* Check if we can free this entry now */
         if (current->ReferenceCount == 0)
         {
+            ASSERT(!current->Dirty);
+            ASSERT(!current->MappedCount);
+
             RemoveEntryList(&current->BcbSegmentListEntry);
-            KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
             RemoveEntryList(&current->CacheSegmentListEntry);
             RemoveEntryList(&current->CacheSegmentLRUListEntry);
             InsertHeadList(&FreeList, &current->BcbSegmentListEntry);
+
+            /* Calculate how many pages we freed for Mm */
+            PagesPerSegment = current->Bcb->CacheSegmentSize / PAGE_SIZE;
+            PagesFreed = min(PagesPerSegment, Target);
+            Target -= PagesFreed;
+            (*NrFreed) += PagesFreed;
         }
-        else
-        {
-            KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
-        }
+
+        KeReleaseSpinLock(&current->Bcb->BcbLock, oldIrql);
     }
-    
+
     KeReleaseGuardedMutex(&ViewLock);
-    
+
     while (!IsListEmpty(&FreeList))
     {
         current_entry = RemoveHeadList(&FreeList);
@@ -383,7 +383,9 @@ CcRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
                                     BcbSegmentListEntry);
         CcRosInternalFreeCacheSegment(current);
     }
-    
+
+    DPRINT1("Evicted %d cache pages\n", (*NrFreed));
+
     return(STATUS_SUCCESS);
 }
 
@@ -597,7 +599,7 @@ CcRosCreateCacheSegment(PBCB Bcb,
   current->DirtySegmentListEntry.Flink = NULL;
   current->DirtySegmentListEntry.Blink = NULL;
   current->ReferenceCount = 1;
-  ExInitializePushLock((PULONG_PTR)&current->Lock);
+  ExInitializePushLock(&current->Lock);
   ExAcquirePushLockExclusive(&current->Lock);
   KeAcquireGuardedMutex(&ViewLock);
 
@@ -688,7 +690,7 @@ CcRosCreateCacheSegment(PBCB Bcb,
   MmLockAddressSpace(MmGetKernelAddressSpace());
   current->BaseAddress = NULL;
   Status = MmCreateMemoryArea(MmGetKernelAddressSpace(),
-                             MEMORY_AREA_CACHE_SEGMENT,
+                             0, // nothing checks for cache_segment mareas, so set to 0
                              &current->BaseAddress,
                              Bcb->CacheSegmentSize,
                              PAGE_READWRITE,
@@ -704,6 +706,18 @@ CcRosCreateCacheSegment(PBCB Bcb,
 #endif
 
   /* Create a virtual mapping for this memory area */
+  MI_SET_USAGE(MI_USAGE_CACHE);
+#if MI_TRACE_PFNS
+  PWCHAR pos = NULL;
+  ULONG len = 0;
+  if ((Bcb->FileObject) && (Bcb->FileObject->FileName.Buffer))
+  {
+    pos = wcsrchr(Bcb->FileObject->FileName.Buffer, '\\');
+    len = wcslen(pos) * sizeof(WCHAR);
+    if (pos) snprintf(MI_PFN_CURRENT_PROCESS_NAME, min(16, len), "%S", pos);
+  }   
+#endif
+
   MmMapMemoryArea(current->BaseAddress, Bcb->CacheSegmentSize,
       MC_CACHE, PAGE_READWRITE);
 
@@ -842,7 +856,7 @@ CcRosRequestCacheSegment(PBCB Bcb,
 #else
 static VOID
 CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
-               PFN_TYPE Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
+               PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty)
 {
   ASSERT(SwapEntry == 0);
   if (Page != 0)
@@ -861,7 +875,7 @@ CcRosInternalFreeCacheSegment(PCACHE_SEGMENT CacheSeg)
   ULONG i;
   ULONG RegionSize;
   ULONG Base;
-  PFN_TYPE Page;
+  PFN_NUMBER Page;
   KIRQL oldIrql;
 #endif
   DPRINT("Freeing cache segment 0x%p\n", CacheSeg);
@@ -1022,7 +1036,6 @@ CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
 {
    PLIST_ENTRY current_entry;
    PCACHE_SEGMENT current;
-   NTSTATUS Status;
    LIST_ENTRY FreeList;
    KIRQL oldIrql;
 
@@ -1077,7 +1090,7 @@ CcRosDeleteFileCache(PFILE_OBJECT FileObject, PBCB Bcb)
       {
          current_entry = RemoveTailList(&FreeList);
          current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, BcbSegmentListEntry);
-         Status = CcRosInternalFreeCacheSegment(current);
+         CcRosInternalFreeCacheSegment(current);
       }
       ExFreeToNPagedLookasideList(&BcbLookasideList, Bcb);
       KeAcquireGuardedMutex(&ViewLock);