Revert 15473 and 15474 as Alex doesn't like them
[reactos.git] / reactos / ntoskrnl / mm / pageop.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/pageop.c
6 * PURPOSE: No purpose listed.
7 *
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* GLOBALS *******************************************************************/
18
19 #define PAGEOP_HASH_TABLE_SIZE (32)
20
21 static KSPIN_LOCK MmPageOpHashTableLock;
22 static PMM_PAGEOP MmPageOpHashTable[PAGEOP_HASH_TABLE_SIZE];
23 static NPAGED_LOOKASIDE_LIST MmPageOpLookasideList;
24
25 /* FUNCTIONS *****************************************************************/
26
27 VOID
28 MmReleasePageOp(PMM_PAGEOP PageOp)
29 /*
30 * FUNCTION: Release a reference to a page operation descriptor
31 */
32 {
33 KIRQL oldIrql;
34 PMM_PAGEOP PrevPageOp;
35
36 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
37 PageOp->ReferenceCount--;
38 if (PageOp->ReferenceCount > 0)
39 {
40 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
41 return;
42 }
43 InterlockedDecrementUL(&PageOp->MArea->PageOpCount);
44 PrevPageOp = MmPageOpHashTable[PageOp->Hash];
45 if (PrevPageOp == PageOp)
46 {
47 MmPageOpHashTable[PageOp->Hash] = PageOp->Next;
48 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
49 ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
50 return;
51 }
52 while (PrevPageOp->Next != NULL)
53 {
54 if (PrevPageOp->Next == PageOp)
55 {
56 PrevPageOp->Next = PageOp->Next;
57 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
58 ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
59 return;
60 }
61 PrevPageOp = PrevPageOp->Next;
62 }
63 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
64 KEBUGCHECK(0);
65 }
66
67 PMM_PAGEOP
68 MmCheckForPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address,
69 PMM_SECTION_SEGMENT Segment, ULONG Offset)
70 {
71 ULONG_PTR Hash;
72 KIRQL oldIrql;
73 PMM_PAGEOP PageOp;
74
75 /*
76 * Calcuate the hash value for pageop structure
77 */
78 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
79 {
80 Hash = (((ULONG_PTR)Segment) | (((ULONG_PTR)Offset) / PAGE_SIZE));
81 }
82 else
83 {
84 Hash = (((ULONG_PTR)Pid) | (((ULONG_PTR)Address) / PAGE_SIZE));
85 }
86 Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
87
88 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
89
90 /*
91 * Check for an existing pageop structure
92 */
93 PageOp = MmPageOpHashTable[Hash];
94 while (PageOp != NULL)
95 {
96 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
97 {
98 if (PageOp->Segment == Segment &&
99 PageOp->Offset == Offset)
100 {
101 break;
102 }
103 }
104 else
105 {
106 if (PageOp->Pid == Pid &&
107 PageOp->Address == Address)
108 {
109 break;
110 }
111 }
112 PageOp = PageOp->Next;
113 }
114
115 /*
116 * If we found an existing pageop then increment the reference count
117 * and return it.
118 */
119 if (PageOp != NULL)
120 {
121 PageOp->ReferenceCount++;
122 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
123 return(PageOp);
124 }
125 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
126 return(NULL);
127 }
128
129 PMM_PAGEOP
130 MmGetPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address,
131 PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOL First)
132 /*
133 * FUNCTION: Get a page operation descriptor corresponding to
134 * the memory area and either the segment, offset pair or the
135 * pid, address pair.
136 */
137 {
138 ULONG_PTR Hash;
139 KIRQL oldIrql;
140 PMM_PAGEOP PageOp;
141
142 /*
143 * Calcuate the hash value for pageop structure
144 */
145 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
146 {
147 Hash = (((ULONG_PTR)Segment) | (((ULONG_PTR)Offset) / PAGE_SIZE));
148 }
149 else
150 {
151 Hash = (((ULONG_PTR)Pid) | (((ULONG_PTR)Address) / PAGE_SIZE));
152 }
153 Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
154
155 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
156
157 /*
158 * Check for an existing pageop structure
159 */
160 PageOp = MmPageOpHashTable[Hash];
161 while (PageOp != NULL)
162 {
163 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
164 {
165 if (PageOp->Segment == Segment &&
166 PageOp->Offset == Offset)
167 {
168 break;
169 }
170 }
171 else
172 {
173 if (PageOp->Pid == Pid &&
174 PageOp->Address == Address)
175 {
176 break;
177 }
178 }
179 PageOp = PageOp->Next;
180 }
181
182 /*
183 * If we found an existing pageop then increment the reference count
184 * and return it.
185 */
186 if (PageOp != NULL)
187 {
188 if (First)
189 {
190 PageOp = NULL;
191 }
192 else
193 {
194 PageOp->ReferenceCount++;
195 }
196 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
197 return(PageOp);
198 }
199
200 /*
201 * Otherwise add a new pageop.
202 */
203 PageOp = ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList);
204 if (PageOp == NULL)
205 {
206 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
207 KEBUGCHECK(0);
208 return(NULL);
209 }
210
211 if (MArea->Type != MEMORY_AREA_SECTION_VIEW)
212 {
213 PageOp->Pid = Pid;
214 PageOp->Address = Address;
215 }
216 else
217 {
218 PageOp->Segment = Segment;
219 PageOp->Offset = Offset;
220 }
221 PageOp->ReferenceCount = 1;
222 PageOp->Next = MmPageOpHashTable[Hash];
223 PageOp->Hash = Hash;
224 PageOp->Thread = PsGetCurrentThread();
225 PageOp->Abandoned = FALSE;
226 PageOp->Status = STATUS_PENDING;
227 PageOp->OpType = OpType;
228 PageOp->MArea = MArea;
229 KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
230 MmPageOpHashTable[Hash] = PageOp;
231 InterlockedIncrementUL(&MArea->PageOpCount);
232
233 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
234 return(PageOp);
235 }
236
237 VOID INIT_FUNCTION
238 MmInitializePageOp(VOID)
239 {
240 memset(MmPageOpHashTable, 0, sizeof(MmPageOpHashTable));
241 KeInitializeSpinLock(&MmPageOpHashTableLock);
242
243 ExInitializeNPagedLookasideList (&MmPageOpLookasideList,
244 NULL,
245 NULL,
246 0,
247 sizeof(MM_PAGEOP),
248 TAG_MM_PAGEOP,
249 50);
250 }
251
252
253
254
255
256
257