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