3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/pageop.c
6 * PURPOSE: No purpose listed.
8 * PROGRAMMERS: David Welch (welch@cwcom.net)
11 /* INCLUDES ****************************************************************/
15 #include <internal/debug.h>
17 #if defined (ALLOC_PRAGMA)
18 #pragma alloc_text(INIT, MmInitializePageOp)
22 /* GLOBALS *******************************************************************/
24 #define PAGEOP_HASH_TABLE_SIZE (32)
26 static KSPIN_LOCK MmPageOpHashTableLock
;
27 static PMM_PAGEOP MmPageOpHashTable
[PAGEOP_HASH_TABLE_SIZE
];
28 static NPAGED_LOOKASIDE_LIST MmPageOpLookasideList
;
30 /* FUNCTIONS *****************************************************************/
34 MmReleasePageOp(PMM_PAGEOP PageOp
)
36 * FUNCTION: Release a reference to a page operation descriptor
40 PMM_PAGEOP PrevPageOp
;
42 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
43 PageOp
->ReferenceCount
--;
44 if (PageOp
->ReferenceCount
> 0)
46 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
49 (void)InterlockedDecrementUL(&PageOp
->MArea
->PageOpCount
);
50 PrevPageOp
= MmPageOpHashTable
[PageOp
->Hash
];
51 if (PrevPageOp
== PageOp
)
53 MmPageOpHashTable
[PageOp
->Hash
] = PageOp
->Next
;
54 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
55 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
58 while (PrevPageOp
->Next
!= NULL
)
60 if (PrevPageOp
->Next
== PageOp
)
62 PrevPageOp
->Next
= PageOp
->Next
;
63 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
64 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
67 PrevPageOp
= PrevPageOp
->Next
;
69 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
75 MmCheckForPageOp(PMEMORY_AREA MArea
, HANDLE Pid
, PVOID Address
,
76 PMM_SECTION_SEGMENT Segment
, ULONG Offset
)
83 * Calcuate the hash value for pageop structure
85 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
87 Hash
= (((ULONG_PTR
)Segment
) | (((ULONG_PTR
)Offset
) / PAGE_SIZE
));
91 Hash
= (((ULONG_PTR
)Pid
) | (((ULONG_PTR
)Address
) / PAGE_SIZE
));
93 Hash
= Hash
% PAGEOP_HASH_TABLE_SIZE
;
95 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
98 * Check for an existing pageop structure
100 PageOp
= MmPageOpHashTable
[Hash
];
101 while (PageOp
!= NULL
)
103 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
105 if (PageOp
->Segment
== Segment
&&
106 PageOp
->Offset
== Offset
)
113 if (PageOp
->Pid
== Pid
&&
114 PageOp
->Address
== Address
)
119 PageOp
= PageOp
->Next
;
123 * If we found an existing pageop then increment the reference count
128 PageOp
->ReferenceCount
++;
129 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
132 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
138 MmGetPageOp(PMEMORY_AREA MArea
, HANDLE Pid
, PVOID Address
,
139 PMM_SECTION_SEGMENT Segment
, ULONG Offset
, ULONG OpType
, BOOLEAN First
)
141 * FUNCTION: Get a page operation descriptor corresponding to
142 * the memory area and either the segment, offset pair or the
151 * Calcuate the hash value for pageop structure
153 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
155 Hash
= (((ULONG_PTR
)Segment
) | (((ULONG_PTR
)Offset
) / PAGE_SIZE
));
159 Hash
= (((ULONG_PTR
)Pid
) | (((ULONG_PTR
)Address
) / PAGE_SIZE
));
161 Hash
= Hash
% PAGEOP_HASH_TABLE_SIZE
;
163 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
166 * Check for an existing pageop structure
168 PageOp
= MmPageOpHashTable
[Hash
];
169 while (PageOp
!= NULL
)
171 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
173 if (PageOp
->Segment
== Segment
&&
174 PageOp
->Offset
== Offset
)
181 if (PageOp
->Pid
== Pid
&&
182 PageOp
->Address
== Address
)
187 PageOp
= PageOp
->Next
;
191 * If we found an existing pageop then increment the reference count
202 PageOp
->ReferenceCount
++;
204 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
209 * Otherwise add a new pageop.
211 PageOp
= ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList
);
214 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
219 if (MArea
->Type
!= MEMORY_AREA_SECTION_VIEW
)
222 PageOp
->Address
= Address
;
226 PageOp
->Segment
= Segment
;
227 PageOp
->Offset
= Offset
;
229 PageOp
->ReferenceCount
= 1;
230 PageOp
->Next
= MmPageOpHashTable
[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
);
241 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
248 MmInitializePageOp(VOID
)
250 memset(MmPageOpHashTable
, 0, sizeof(MmPageOpHashTable
));
251 KeInitializeSpinLock(&MmPageOpHashTableLock
);
253 ExInitializeNPagedLookasideList (&MmPageOpLookasideList
,