2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/pageop.c
5 * PURPOSE: No purpose listed.
7 * PROGRAMMERS: David Welch (welch@cwcom.net)
10 /* INCLUDES ****************************************************************/
16 #if defined (ALLOC_PRAGMA)
17 #pragma alloc_text(INIT, MmInitializePageOp)
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 /* 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 (void)InterlockedDecrementUL(&PageOp
->MArea
->PageOpCount
);
49 PrevPageOp
= MmPageOpHashTable
[PageOp
->Hash
];
50 if (PrevPageOp
== PageOp
)
52 MmPageOpHashTable
[PageOp
->Hash
] = PageOp
->Next
;
53 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
54 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
57 while (PrevPageOp
->Next
!= NULL
)
59 if (PrevPageOp
->Next
== PageOp
)
61 PrevPageOp
->Next
= PageOp
->Next
;
62 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
63 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
66 PrevPageOp
= PrevPageOp
->Next
;
68 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
69 KeBugCheck(MEMORY_MANAGEMENT
);
74 MmCheckForPageOp(PMEMORY_AREA MArea
, HANDLE 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_PTR
)Segment
) | (((ULONG_PTR
)Offset
) / PAGE_SIZE
));
90 Hash
= (((ULONG_PTR
)Pid
) | (((ULONG_PTR
)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
);
137 MmGetPageOp(PMEMORY_AREA MArea
, HANDLE Pid
, PVOID Address
,
138 PMM_SECTION_SEGMENT Segment
, ULONG Offset
, ULONG OpType
, BOOLEAN First
)
140 * FUNCTION: Get a page operation descriptor corresponding to
141 * the memory area and either the segment, offset pair or the
150 * Calcuate the hash value for pageop structure
152 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
154 Hash
= (((ULONG_PTR
)Segment
) | (((ULONG_PTR
)Offset
) / PAGE_SIZE
));
158 Hash
= (((ULONG_PTR
)Pid
) | (((ULONG_PTR
)Address
) / PAGE_SIZE
));
160 Hash
= Hash
% PAGEOP_HASH_TABLE_SIZE
;
162 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
165 * Check for an existing pageop structure
167 PageOp
= MmPageOpHashTable
[Hash
];
168 while (PageOp
!= NULL
)
170 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
172 if (PageOp
->Segment
== Segment
&&
173 PageOp
->Offset
== Offset
)
180 if (PageOp
->Pid
== Pid
&&
181 PageOp
->Address
== Address
)
186 PageOp
= PageOp
->Next
;
190 * If we found an existing pageop then increment the reference count
201 PageOp
->ReferenceCount
++;
203 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
208 * Otherwise add a new pageop.
210 PageOp
= ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList
);
213 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
214 KeBugCheck(MEMORY_MANAGEMENT
);
218 if (MArea
->Type
!= MEMORY_AREA_SECTION_VIEW
)
221 PageOp
->Address
= Address
;
225 PageOp
->Segment
= Segment
;
226 PageOp
->Offset
= Offset
;
228 PageOp
->ReferenceCount
= 1;
229 PageOp
->Next
= MmPageOpHashTable
[Hash
];
231 PageOp
->Thread
= PsGetCurrentThread();
232 PageOp
->Abandoned
= FALSE
;
233 PageOp
->Status
= STATUS_PENDING
;
234 PageOp
->OpType
= OpType
;
235 PageOp
->MArea
= MArea
;
236 KeInitializeEvent(&PageOp
->CompletionEvent
, NotificationEvent
, FALSE
);
237 MmPageOpHashTable
[Hash
] = PageOp
;
238 (void)InterlockedIncrementUL(&MArea
->PageOpCount
);
240 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
247 MmInitializePageOp(VOID
)
249 memset(MmPageOpHashTable
, 0, sizeof(MmPageOpHashTable
));
250 KeInitializeSpinLock(&MmPageOpHashTableLock
);
252 ExInitializeNPagedLookasideList (&MmPageOpLookasideList
,