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 /* GLOBALS *******************************************************************/
19 #define PAGEOP_HASH_TABLE_SIZE (32)
21 static KSPIN_LOCK MmPageOpHashTableLock
;
22 static PMM_PAGEOP MmPageOpHashTable
[PAGEOP_HASH_TABLE_SIZE
];
23 static NPAGED_LOOKASIDE_LIST MmPageOpLookasideList
;
25 /* FUNCTIONS *****************************************************************/
28 MmReleasePageOp(PMM_PAGEOP PageOp
)
30 * FUNCTION: Release a reference to a page operation descriptor
34 PMM_PAGEOP PrevPageOp
;
36 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
37 PageOp
->ReferenceCount
--;
38 if (PageOp
->ReferenceCount
> 0)
40 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
43 InterlockedDecrementUL(&PageOp
->MArea
->PageOpCount
);
44 PrevPageOp
= MmPageOpHashTable
[PageOp
->Hash
];
45 if (PrevPageOp
== PageOp
)
47 MmPageOpHashTable
[PageOp
->Hash
] = PageOp
->Next
;
48 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
49 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
52 while (PrevPageOp
->Next
!= NULL
)
54 if (PrevPageOp
->Next
== PageOp
)
56 PrevPageOp
->Next
= PageOp
->Next
;
57 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
58 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
61 PrevPageOp
= PrevPageOp
->Next
;
63 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
68 MmCheckForPageOp(PMEMORY_AREA MArea
, HANDLE Pid
, PVOID Address
,
69 PMM_SECTION_SEGMENT Segment
, ULONG Offset
)
76 * Calcuate the hash value for pageop structure
78 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
80 Hash
= (((ULONG_PTR
)Segment
) | (((ULONG_PTR
)Offset
) / PAGE_SIZE
));
84 Hash
= (((ULONG_PTR
)Pid
) | (((ULONG_PTR
)Address
) / PAGE_SIZE
));
86 Hash
= Hash
% PAGEOP_HASH_TABLE_SIZE
;
88 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
91 * Check for an existing pageop structure
93 PageOp
= MmPageOpHashTable
[Hash
];
94 while (PageOp
!= NULL
)
96 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
98 if (PageOp
->Segment
== Segment
&&
99 PageOp
->Offset
== Offset
)
106 if (PageOp
->Pid
== Pid
&&
107 PageOp
->Address
== Address
)
112 PageOp
= PageOp
->Next
;
116 * If we found an existing pageop then increment the reference count
121 PageOp
->ReferenceCount
++;
122 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
125 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
130 MmGetPageOp(PMEMORY_AREA MArea
, HANDLE Pid
, PVOID Address
,
131 PMM_SECTION_SEGMENT Segment
, ULONG Offset
, ULONG OpType
, BOOL First
)
133 * FUNCTION: Get a page operation descriptor corresponding to
134 * the memory area and either the segment, offset pair or the
143 * Calcuate the hash value for pageop structure
145 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
147 Hash
= (((ULONG_PTR
)Segment
) | (((ULONG_PTR
)Offset
) / PAGE_SIZE
));
151 Hash
= (((ULONG_PTR
)Pid
) | (((ULONG_PTR
)Address
) / PAGE_SIZE
));
153 Hash
= Hash
% PAGEOP_HASH_TABLE_SIZE
;
155 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
158 * Check for an existing pageop structure
160 PageOp
= MmPageOpHashTable
[Hash
];
161 while (PageOp
!= NULL
)
163 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
165 if (PageOp
->Segment
== Segment
&&
166 PageOp
->Offset
== Offset
)
173 if (PageOp
->Pid
== Pid
&&
174 PageOp
->Address
== Address
)
179 PageOp
= PageOp
->Next
;
183 * If we found an existing pageop then increment the reference count
194 PageOp
->ReferenceCount
++;
196 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
201 * Otherwise add a new pageop.
203 PageOp
= ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList
);
206 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
211 if (MArea
->Type
!= MEMORY_AREA_SECTION_VIEW
)
214 PageOp
->Address
= Address
;
218 PageOp
->Segment
= Segment
;
219 PageOp
->Offset
= Offset
;
221 PageOp
->ReferenceCount
= 1;
222 PageOp
->Next
= MmPageOpHashTable
[Hash
];
224 PageOp
->Thread
= PsGetCurrentThread();
225 PageOp
->Abandoned
= FALSE
;
226 PageOp
->Status
= STATUS_PENDING
;
227 PageOp
->OpType
= OpType
;
228 PageOp
->MArea
= MArea
;
229 KeInitializeEvent(&PageOp
->CompletionEvent
, NotificationEvent
, FALSE
);
230 MmPageOpHashTable
[Hash
] = PageOp
;
231 InterlockedIncrementUL(&MArea
->PageOpCount
);
233 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
238 MmInitializePageOp(VOID
)
240 memset(MmPageOpHashTable
, 0, sizeof(MmPageOpHashTable
));
241 KeInitializeSpinLock(&MmPageOpHashTableLock
);
243 ExInitializeNPagedLookasideList (&MmPageOpLookasideList
,