666d339d934b2cff3b55a002e0a1c6dfc11bcbbe
[reactos.git] / reactos / ntoskrnl / cc / view.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/cc/view.c
5 * PURPOSE: Cache manager
6 * PROGRAMMER: David Welch (welch@mcmail.com)
7 * UPDATE HISTORY:
8 * Created 22/05/98
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <ddk/ntifs.h>
15 #include <internal/mm.h>
16
17 //#define NDEBUG
18 #include <internal/debug.h>
19
20 /* TYPES *********************************************************************/
21
22 #define CACHE_SEGMENT_SIZE (0x1000)
23
24 typedef struct _CACHE_SEGMENT
25 {
26 PVOID BaseAddress;
27 PMEMORY_AREA MemoryArea;
28 BOOLEAN Valid;
29 LIST_ENTRY ListEntry;
30 ULONG FileOffset;
31 KEVENT Lock;
32 ULONG ReferenceCount;
33 } CACHE_SEGMENT, *PCACHE_SEGMENT;
34
35 /* FUNCTIONS *****************************************************************/
36
37 NTSTATUS CcRequestCachePage(PBCB Bcb,
38 ULONG FileOffset,
39 PVOID* BaseAddress,
40 PBOOLEAN UptoDate)
41 {
42 KIRQL oldirql;
43 PLIST_ENTRY current_entry;
44 PCACHE_SEGMENT current;
45
46 DPRINT("CcRequestCachePage(Bcb %x, FileOffset %x)\n");
47
48 KeAcquireSpinLock(&Bcb->BcbLock, &oldirql);
49
50 current_entry = Bcb->CacheSegmentListHead.Flink;
51 while (current_entry != &Bcb->CacheSegmentListHead)
52 {
53 current = CONTAINING_RECORD(current_entry, CACHE_SEGMENT, ListEntry);
54 if (current->FileOffset == PAGE_ROUND_DOWN(FileOffset))
55 {
56 current->ReferenceCount++;
57 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
58 KeWaitForSingleObject(&current->Lock,
59 Executive,
60 KernelMode,
61 FALSE,
62 NULL);
63 *UptoDate = current->Valid;
64 BaseAddress = current->BaseAddress;
65 return(STATUS_SUCCESS);
66 }
67 current_entry = current_entry->Flink;
68 }
69
70 current = ExAllocatePool(NonPagedPool, sizeof(CACHE_SEGMENT));
71 current->BaseAddress = NULL;
72 MmCreateMemoryArea(KernelMode,
73 PsGetCurrentProcess(),
74 MEMORY_AREA_CACHE_SEGMENT,
75 &current->BaseAddress,
76 CACHE_SEGMENT_SIZE,
77 PAGE_READWRITE,
78 &current->MemoryArea);
79 current->Valid = FALSE;
80 current->FileOffset = PAGE_ROUND_DOWN(FileOffset);
81 KeInitializeEvent(&current->Lock, SynchronizationEvent, TRUE);
82 current->ReferenceCount = 1;
83 InsertTailList(&Bcb->CacheSegmentListHead, &current->ListEntry);
84 *UptoDate = current->Valid;
85 *BaseAddress = current->BaseAddress;
86 MmSetPage(PsGetCurrentProcess(),
87 current->BaseAddress,
88 (ULONG)MmAllocPage(),
89 PAGE_READWRITE);
90
91 KeReleaseSpinLock(&Bcb->BcbLock, oldirql);
92
93 return(STATUS_SUCCESS);
94 }
95
96 NTSTATUS CcInitializeFileCache(PFILE_OBJECT FileObject,
97 PBCB* Bcb)
98 {
99 DPRINT("CcInitializeFileCache(FileObject %x)\n",FileObject);
100
101 (*Bcb) = ExAllocatePool(NonPagedPool, sizeof(BCB));
102 if ((*Bcb) == NULL)
103 {
104 return(STATUS_UNSUCCESSFUL);
105 }
106
107 (*Bcb)->FileObject = FileObject;
108 InitializeListHead(&(*Bcb)->CacheSegmentListHead);
109 KeInitializeSpinLock(&(*Bcb)->BcbLock);
110
111 DPRINT("Finished CcInitializeFileCache() = %x\n", *Bcb);
112
113 return(STATUS_SUCCESS);
114 }
115
116
117