3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/pageop.c
6 * PROGRAMMER: David Welch (welch@cwcom.net)
11 /* INCLUDES ****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/ps.h>
15 #include <internal/mm.h>
16 #include <internal/pool.h>
19 #include <internal/debug.h>
21 /* GLOBALS *******************************************************************/
23 #define PAGEOP_HASH_TABLE_SIZE (32)
25 static KSPIN_LOCK MmPageOpHashTableLock;
26 static PMM_PAGEOP MmPageOpHashTable[PAGEOP_HASH_TABLE_SIZE];
27 static NPAGED_LOOKASIDE_LIST MmPageOpLookasideList;
29 #define TAG_MM_PAGEOP TAG('M', 'P', 'O', 'P')
31 /* 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 InterlockedDecrement((LONG *)&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);
74 MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
75 PMM_SECTION_SEGMENT Segment, ULONG Offset)
82 * Calcuate the hash value for pageop structure
84 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
86 Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
90 Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
92 Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
94 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
97 * Check for an existing pageop structure
99 PageOp = MmPageOpHashTable[Hash];
100 while (PageOp != NULL)
102 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
104 if (PageOp->Segment == Segment &&
105 PageOp->Offset == Offset)
112 if (PageOp->Pid == Pid &&
113 PageOp->Address == Address)
118 PageOp = PageOp->Next;
122 * If we found an existing pageop then increment the reference count
127 PageOp->ReferenceCount++;
128 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
131 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
136 MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
137 PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType)
139 * FUNCTION: Get a page operation descriptor corresponding to
140 * the memory area and either the segment, offset pair or the
149 * Calcuate the hash value for pageop structure
151 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
153 Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
157 Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
159 Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
161 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
164 * Check for an existing pageop structure
166 PageOp = MmPageOpHashTable[Hash];
167 while (PageOp != NULL)
169 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
171 if (PageOp->Segment == Segment &&
172 PageOp->Offset == Offset)
179 if (PageOp->Pid == Pid &&
180 PageOp->Address == Address)
185 PageOp = PageOp->Next;
189 * If we found an existing pageop then increment the reference count
194 PageOp->ReferenceCount++;
195 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
200 * Otherwise add a new pageop.
202 PageOp = ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList);
205 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
209 if (MArea->Type != MEMORY_AREA_SECTION_VIEW)
212 PageOp->Address = Address;
216 PageOp->Segment = Segment;
217 PageOp->Offset = Offset;
219 PageOp->ReferenceCount = 1;
220 PageOp->Next = MmPageOpHashTable[Hash];
222 PageOp->Thread = PsGetCurrentThread();
223 PageOp->Abandoned = FALSE;
224 PageOp->Status = STATUS_PENDING;
225 PageOp->OpType = OpType;
226 PageOp->MArea = MArea;
227 KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
228 MmPageOpHashTable[Hash] = PageOp;
229 InterlockedIncrement((LONG *)&MArea->PageOpCount);
231 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
236 MmInitializePageOp(VOID)
238 memset(MmPageOpHashTable, 0, sizeof(MmPageOpHashTable));
239 KeInitializeSpinLock(&MmPageOpHashTableLock);
241 ExInitializeNPagedLookasideList (&MmPageOpLookasideList,