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 ****************************************************************/
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 #define TAG_MM_PAGEOP TAG('M', 'P', 'O', 'P')
27 /* FUNCTIONS *****************************************************************/
30 MmReleasePageOp(PMM_PAGEOP PageOp
)
32 * FUNCTION: Release a reference to a page operation descriptor
36 PMM_PAGEOP PrevPageOp
;
38 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
39 PageOp
->ReferenceCount
--;
40 if (PageOp
->ReferenceCount
> 0)
42 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
45 InterlockedDecrementUL(&PageOp
->MArea
->PageOpCount
);
46 PrevPageOp
= MmPageOpHashTable
[PageOp
->Hash
];
47 if (PrevPageOp
== PageOp
)
49 MmPageOpHashTable
[PageOp
->Hash
] = PageOp
->Next
;
50 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
51 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
54 while (PrevPageOp
->Next
!= NULL
)
56 if (PrevPageOp
->Next
== PageOp
)
58 PrevPageOp
->Next
= PageOp
->Next
;
59 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
60 ExFreeToNPagedLookasideList(&MmPageOpLookasideList
, PageOp
);
63 PrevPageOp
= PrevPageOp
->Next
;
65 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
70 MmCheckForPageOp(PMEMORY_AREA MArea
, ULONG Pid
, PVOID Address
,
71 PMM_SECTION_SEGMENT Segment
, ULONG Offset
)
78 * Calcuate the hash value for pageop structure
80 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
82 Hash
= (((ULONG
)Segment
) | (((ULONG
)Offset
) / PAGE_SIZE
));
86 Hash
= (((ULONG
)Pid
) | (((ULONG
)Address
) / PAGE_SIZE
));
88 Hash
= Hash
% PAGEOP_HASH_TABLE_SIZE
;
90 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
93 * Check for an existing pageop structure
95 PageOp
= MmPageOpHashTable
[Hash
];
96 while (PageOp
!= NULL
)
98 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
100 if (PageOp
->Segment
== Segment
&&
101 PageOp
->Offset
== Offset
)
108 if (PageOp
->Pid
== Pid
&&
109 PageOp
->Address
== Address
)
114 PageOp
= PageOp
->Next
;
118 * If we found an existing pageop then increment the reference count
123 PageOp
->ReferenceCount
++;
124 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
127 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
132 MmGetPageOp(PMEMORY_AREA MArea
, ULONG Pid
, PVOID Address
,
133 PMM_SECTION_SEGMENT Segment
, ULONG Offset
, ULONG OpType
, BOOL First
)
135 * FUNCTION: Get a page operation descriptor corresponding to
136 * the memory area and either the segment, offset pair or the
145 * Calcuate the hash value for pageop structure
147 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
149 Hash
= (((ULONG
)Segment
) | (((ULONG
)Offset
) / PAGE_SIZE
));
153 Hash
= (((ULONG
)Pid
) | (((ULONG
)Address
) / PAGE_SIZE
));
155 Hash
= Hash
% PAGEOP_HASH_TABLE_SIZE
;
157 KeAcquireSpinLock(&MmPageOpHashTableLock
, &oldIrql
);
160 * Check for an existing pageop structure
162 PageOp
= MmPageOpHashTable
[Hash
];
163 while (PageOp
!= NULL
)
165 if (MArea
->Type
== MEMORY_AREA_SECTION_VIEW
)
167 if (PageOp
->Segment
== Segment
&&
168 PageOp
->Offset
== Offset
)
175 if (PageOp
->Pid
== Pid
&&
176 PageOp
->Address
== Address
)
181 PageOp
= PageOp
->Next
;
185 * If we found an existing pageop then increment the reference count
196 PageOp
->ReferenceCount
++;
198 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
203 * Otherwise add a new pageop.
205 PageOp
= ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList
);
208 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
213 if (MArea
->Type
!= MEMORY_AREA_SECTION_VIEW
)
216 PageOp
->Address
= Address
;
220 PageOp
->Segment
= Segment
;
221 PageOp
->Offset
= Offset
;
223 PageOp
->ReferenceCount
= 1;
224 PageOp
->Next
= MmPageOpHashTable
[Hash
];
226 PageOp
->Thread
= PsGetCurrentThread();
227 PageOp
->Abandoned
= FALSE
;
228 PageOp
->Status
= STATUS_PENDING
;
229 PageOp
->OpType
= OpType
;
230 PageOp
->MArea
= MArea
;
231 KeInitializeEvent(&PageOp
->CompletionEvent
, NotificationEvent
, FALSE
);
232 MmPageOpHashTable
[Hash
] = PageOp
;
233 InterlockedIncrementUL(&MArea
->PageOpCount
);
235 KeReleaseSpinLock(&MmPageOpHashTableLock
, oldIrql
);
240 MmInitializePageOp(VOID
)
242 memset(MmPageOpHashTable
, 0, sizeof(MmPageOpHashTable
));
243 KeInitializeSpinLock(&MmPageOpHashTableLock
);
245 ExInitializeNPagedLookasideList (&MmPageOpLookasideList
,