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 KSPIN_LOCK MmPageOpHashTableLock;
26 PMM_PAGEOP MmPageOpHashTable[PAGEOP_HASH_TABLE_SIZE] = {NULL, } ;
28 #define TAG_MM_PAGEOP TAG('M', 'P', 'O', 'P')
30 /* FUNCTIONS *****************************************************************/
33 MmReleasePageOp(PMM_PAGEOP PageOp)
35 * FUNCTION: Release a reference to a page operation descriptor
39 PMM_PAGEOP PrevPageOp;
41 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
42 PageOp->ReferenceCount--;
43 if (PageOp->ReferenceCount > 0)
45 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
48 InterlockedDecrement(&PageOp->MArea->PageOpCount);
49 PrevPageOp = MmPageOpHashTable[PageOp->Hash];
50 if (PrevPageOp == PageOp)
52 MmPageOpHashTable[PageOp->Hash] = PageOp->Next;
53 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
57 while (PrevPageOp->Next != NULL)
59 if (PrevPageOp->Next == PageOp)
61 PrevPageOp->Next = PageOp->Next;
62 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
66 PrevPageOp = PrevPageOp->Next;
68 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
73 MmCheckForPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
74 PMM_SECTION_SEGMENT Segment, ULONG Offset)
81 * Calcuate the hash value for pageop structure
83 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
85 Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
89 Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
91 Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
93 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
96 * Check for an existing pageop structure
98 PageOp = MmPageOpHashTable[Hash];
99 while (PageOp != NULL)
101 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
103 if (PageOp->Segment == Segment &&
104 PageOp->Offset == Offset)
111 if (PageOp->Pid == Pid &&
112 PageOp->Address == Address)
117 PageOp = PageOp->Next;
121 * If we found an existing pageop then increment the reference count
126 PageOp->ReferenceCount++;
127 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
130 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
135 MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address,
136 PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType)
138 * FUNCTION: Get a page operation descriptor corresponding to
139 * the memory area and either the segment, offset pair or the
148 * Calcuate the hash value for pageop structure
150 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
152 Hash = (((ULONG)Segment) | (((ULONG)Offset) / PAGE_SIZE));
156 Hash = (((ULONG)Pid) | (((ULONG)Address) / PAGE_SIZE));
158 Hash = Hash % PAGEOP_HASH_TABLE_SIZE;
160 KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
163 * Check for an existing pageop structure
165 PageOp = MmPageOpHashTable[Hash];
166 while (PageOp != NULL)
168 if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
170 if (PageOp->Segment == Segment &&
171 PageOp->Offset == Offset)
178 if (PageOp->Pid == Pid &&
179 PageOp->Address == Address)
184 PageOp = PageOp->Next;
188 * If we found an existing pageop then increment the reference count
193 PageOp->ReferenceCount++;
194 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
199 * Otherwise add a new pageop.
201 PageOp = ExAllocatePoolWithTag(NonPagedPool, sizeof(MM_PAGEOP),
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(&MArea->PageOpCount);
231 KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);