diff --git a/reactos/ntoskrnl/include/internal/mm.h b/reactos/ntoskrnl/include/internal/mm.h index 998fe9fc86d..4ffc1b4698f 100644 --- a/reactos/ntoskrnl/include/internal/mm.h +++ b/reactos/ntoskrnl/include/internal/mm.h @@ -333,17 +333,24 @@ typedef struct extern MM_STATS MmStats; -NTSTATUS MmWritePageSectionView(PMADDRESS_SPACE AddressSpace, - PMEMORY_AREA MArea, - PVOID Address); -NTSTATUS MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace, - PMEMORY_AREA MArea, - PVOID Address); -PVOID MmGetDirtyPagesFromWorkingSet(struct _EPROCESS* Process); -NTSTATUS MmWriteToSwapPage(SWAPENTRY SwapEntry, PMDL Mdl); -NTSTATUS MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl); -VOID MmSetFlagsPage(PVOID PhysicalAddress, ULONG Flags); -ULONG MmGetFlagsPage(PVOID PhysicalAddress); +NTSTATUS +MmWritePageSectionView(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MArea, + PVOID Address); +NTSTATUS +MmWritePageVirtualMemory(PMADDRESS_SPACE AddressSpace, + PMEMORY_AREA MArea, + PVOID Address); +PVOID +MmGetDirtyPagesFromWorkingSet(struct _EPROCESS* Process); +NTSTATUS +MmWriteToSwapPage(SWAPENTRY SwapEntry, PMDL Mdl); +NTSTATUS +MmReadFromSwapPage(SWAPENTRY SwapEntry, PMDL Mdl); +VOID +MmSetFlagsPage(PVOID PhysicalAddress, ULONG Flags); +ULONG +MmGetFlagsPage(PVOID PhysicalAddress); VOID MmSetSavedSwapEntryPage(PVOID PhysicalAddress, SWAPENTRY SavedSwapEntry); SWAPENTRY MmGetSavedSwapEntryPage(PVOID PhysicalAddress); @@ -375,4 +382,33 @@ MmGetReferenceCountPage(PVOID PhysicalAddress); BOOLEAN MmIsUsablePage(PVOID PhysicalAddress); +typedef struct _MM_PAGEOP +{ + /* Type of operation. */ + ULONG OpType; + /* Number of threads interested in this operation. */ + ULONG ReferenceCount; + /* Event that will be set when the operation is completed. */ + KEVENT CompletionEvent; + /* Status of the operation once it is completed. */ + NTSTATUS Status; + /* TRUE if the operation was abandoned. */ + BOOLEAN Abandoned; + /* The memory area to be affected by the operation. */ + PMEMORY_AREA MArea; + struct _MM_PAGEOP* Next; + /* + * These fields are used to identify the operation if it is against a + * virtual memory area. + */ + ULONG Pid; + PVOID Address; + /* + * These fields are used to identify the operation if it is against a + * section mapping. + */ + PMM_SECTION_SEGMENT Segment; + ULONG Offset; +} MM_PAGEOP, *PMM_PAGEOP; + #endif diff --git a/reactos/ntoskrnl/kd/dlog.c b/reactos/ntoskrnl/kd/dlog.c new file mode 100644 index 00000000000..388b4f9457a --- /dev/null +++ b/reactos/ntoskrnl/kd/dlog.c @@ -0,0 +1,219 @@ +/* $Id: dlog.c,v 1.1 2001/02/16 18:32:20 dwelch Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/kd/kdebug.c + * PURPOSE: Kernel debugger + * PROGRAMMER: Eric Kohl (ekohl@abo.rhein-zeitung.de) + * UPDATE HISTORY: + * 21/10/99: Created + */ + +/* INCLUDES ******************************************************************/ + +#include +#include +#include +#include + +/* GLOBALS *******************************************************************/ + +#define DEBUGLOG_SIZE (32*1024) + +#ifdef DBGPRINT_FILE_LOG + +static CHAR DebugLog[DEBUGLOG_SIZE]; +static ULONG DebugLogStart; +static ULONG DebugLogEnd; +static KSPIN_LOCK DebugLogLock; +static ULONG DebugLogOverflow; +static HANDLE DebugLogThreadHandle; +static CLIENT_ID DebugLogThreadCid; +static HANDLE DebugLogFile; +static KSEMAPHORE DebugLogSem; + +#endif /* DBGPRINT_FILE_LOG */ + +/* FUNCTIONS *****************************************************************/ + +#ifdef DBGPRINT_FILE_LOG + +VOID +DebugLogInit(VOID) +{ + KeInitializeSpinLock(&DebugLogLock); + DebugLogStart = -1; + DebugLogEnd = 0; + DebugLogOverflow = 0; + KeInitializeSemaphore(&DebugLogSem, 0, 255); +} + +NTSTATUS +DebugLogThreadMain(PVOID Context) +{ + KIRQL oldIrql; + IO_STATUS_BLOCK Iosb; + CHAR Buffer[256]; + ULONG WLen; + + for (;;) + { + KeWaitForSingleObject(&DebugLogSem, + 0, + KernelMode, + FALSE, + NULL); + KeAcquireSpinLock(&DebugLogLock, &oldIrql); + while (DebugLogStart != -1) + { + if (DebugLogStart > DebugLogEnd) + { + WLen = min(256, DEBUGLOG_SIZE - DebugLogStart); + memcpy(Buffer, &DebugLog[DebugLogStart], WLen); + DebugLogStart = + (DebugLogStart + WLen) % DEBUGLOG_SIZE; + if (DebugLogStart == DebugLogEnd) + { + DebugLogStart = -1; + } + KeReleaseSpinLock(&DebugLogLock, oldIrql); + NtWriteFile(DebugLogFile, + NULL, + NULL, + NULL, + &Iosb, + Buffer, + WLen, + NULL, + NULL); + } + else + { + WLen = min(256, DebugLogEnd - DebugLogStart); + memcpy(Buffer, &DebugLog[DebugLogStart], WLen); + DebugLogStart = + (DebugLogStart + WLen) % DEBUGLOG_SIZE; + if (DebugLogStart == DebugLogEnd) + { + DebugLogStart = -1; + } + KeReleaseSpinLock(&DebugLogLock, oldIrql); + NtWriteFile(DebugLogFile, + NULL, + NULL, + NULL, + &Iosb, + Buffer, + WLen, + NULL, + NULL); + } + KeAcquireSpinLock(&DebugLogLock, &oldIrql); + } + KeReleaseSpinLock(&DebugLogLock, oldIrql); + } +} + +VOID +DebugLogInit2(VOID) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES ObjectAttributes; + UNICODE_STRING FileName; + IO_STATUS_BLOCK Iosb; + + RtlInitUnicodeString(&FileName, L"\\SystemRoot\\debug.log"); + InitializeObjectAttributes(&ObjectAttributes, + &FileName, + 0, + NULL, + NULL); + + Status = NtCreateFile(&DebugLogFile, + FILE_ALL_ACCESS, + &ObjectAttributes, + &Iosb, + NULL, + FILE_ATTRIBUTE_NORMAL, + 0, + FILE_SUPERSEDE, + FILE_WRITE_THROUGH | FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + if (!NT_SUCCESS(Status)) + { + DbgPrint("Failed to create debug log file\n"); + return; + } + + Status = PsCreateSystemThread(&DebugLogThreadHandle, + THREAD_ALL_ACCESS, + NULL, + NULL, + &DebugLogThreadCid, + DebugLogThreadMain, + NULL); +} + + VOID + DebugLogWrite(PCH String) + { + KIRQL oldIrql; + + if (KeGetCurrentIrql() > DISPATCH_LEVEL) + { + DebugLogOverflow++; + return; + } + + KeAcquireSpinLock(&DebugLogLock, &oldIrql); + + if (DebugLogEnd == DebugLogStart) + { + DebugLogOverflow++; + KeReleaseSpinLock(&DebugLogLock, oldIrql); + KeReleaseSemaphore(&DebugLogSem, IO_NO_INCREMENT, 1, FALSE); + return; + } + if (DebugLogStart == -1) + { + DebugLogStart = DebugLogEnd; + } + + while ((*String) != 0) + { + DebugLog[DebugLogEnd] = *String; + String++; + if (((DebugLogEnd + 1) % DEBUGLOG_SIZE) == DebugLogStart) + { + DebugLogOverflow++; + KeReleaseSpinLock(&DebugLogLock, oldIrql); + KeReleaseSemaphore(&DebugLogSem, IO_NO_INCREMENT, 1, FALSE); + return; + } + DebugLogEnd = (DebugLogEnd + 1) % DEBUGLOG_SIZE; + } + + KeReleaseSpinLock(&DebugLogLock, oldIrql); + KeReleaseSemaphore(&DebugLogSem, IO_NO_INCREMENT, 1, FALSE); + } + + #else /* not DBGPRINT_FILE_LOG */ + + VOID + DebugLogInit(VOID) + { + } + +VOID +DebugLogInit2(VOID) +{ +} + +VOID +DebugLogWrite(PCH String) +{ +} + +#endif /* DBGPRINT_FILE_LOG */ + diff --git a/reactos/ntoskrnl/ke/i386/irqhand.c b/reactos/ntoskrnl/ke/i386/irqhand.c deleted file mode 100644 index 7417cf0be0b..00000000000 --- a/reactos/ntoskrnl/ke/i386/irqhand.c +++ /dev/null @@ -1,83 +0,0 @@ - -#include -#include -#include -#include - - -#define _STR(x) #x -#define STR(x) _STR(x) - - -#define IRQ_HANDLER_FIRST(x,y) \ - void irq_handler_##y (void); \ - __asm__("\n\t.global _irq_handler_"##x"\n\t_irq_handler_"##x":\n\t" \ - "pusha\n\t" \ - "pushl %ds\n\t" \ - "pushl %es\n\t" \ - "pushl %fs\n\t" \ - "movl $0xceafbeef,%eax\n\t" \ - "pushl %eax\n\t" \ - "movw $"STR(KERNEL_DS)",%ax\n\t" \ - "movw %ax,%ds\n\t" \ - "movw %ax,%es\n\t" \ - "inb $0x21,%al\n\t" \ - "orb $1<<"##x",%al\n\t" \ - "outb %al,$0x21\n\t" \ - "pushl %esp\n\t" \ - "pushl $"##x"\n\t" \ - "call _KiInterruptDispatch\n\t"\ - "popl %eax\n\t" \ - "popl %eax\n\t" \ - "popl %eax\n\t" \ - "popl %fs\n\t" \ - "popl %es\n\t" \ - "popl %ds\n\t" \ - "popa\n\t" \ - "iret\n\t") - -#define IRQ_HANDLER_SECOND(x,y) \ - void irq_handler_##y (void); \ - __asm__("\n\t.global _irq_handler_"##x"\n\t_irq_handler_"##x":\n\t" \ - "pusha\n\t" \ - "pushl %ds\n\t" \ - "pushl %es\n\t" \ - "pushl %fs\n\t" \ - "movl $0xceafbeef,%eax\n\t" \ - "pushl %eax\n\t" \ - "movw $"STR(KERNEL_DS)",%ax\n\t" \ - "movw %ax,%ds\n\t" \ - "movw %ax,%es\n\t" \ - "inb $0xa1,%al\n\t" \ - "orb $1<<("##x"-8),%al\n\t" \ - "outb %al,$0xa1\n\t" \ - "pushl %esp\n\t" \ - "pushl $"##x"\n\t" \ - "call _KiInterruptDispatch\n\t"\ - "popl %eax\n\t" \ - "popl %eax\n\t" \ - "popl %eax\n\t" \ - "popl %fs\n\t" \ - "popl %es\n\t" \ - "popl %ds\n\t" \ - "popa\n\t" \ - "iret\n\t") - - -IRQ_HANDLER_FIRST ("0",0); -IRQ_HANDLER_FIRST ("1",1); -IRQ_HANDLER_FIRST ("2",2); -IRQ_HANDLER_FIRST ("3",3); -IRQ_HANDLER_FIRST ("4",4); -IRQ_HANDLER_FIRST ("5",5); -IRQ_HANDLER_FIRST ("6",6); -IRQ_HANDLER_FIRST ("7",7); -IRQ_HANDLER_SECOND ("8",8); -IRQ_HANDLER_SECOND ("9",9); -IRQ_HANDLER_SECOND ("10",10); -IRQ_HANDLER_SECOND ("11",11); -IRQ_HANDLER_SECOND ("12",12); -IRQ_HANDLER_SECOND ("13",13); -IRQ_HANDLER_SECOND ("14",14); -IRQ_HANDLER_SECOND ("15",15); - diff --git a/reactos/ntoskrnl/ke/i386/irqhand.s b/reactos/ntoskrnl/ke/i386/irqhand.s new file mode 100644 index 00000000000..16508be416d --- /dev/null +++ b/reactos/ntoskrnl/ke/i386/irqhand.s @@ -0,0 +1,420 @@ + +#include + +.global _irq_handler_0 +_irq_handler_0: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<0,%al + outb %al,$0x21 + pushl %esp + pushl $0 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_1 +_irq_handler_1: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<1,%al + outb %al,$0x21 + pushl %esp + pushl $1 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_2 +_irq_handler_2: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<2,%al + outb %al,$0x21 + pushl %esp + pushl $2 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_3 +_irq_handler_3: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<3,%al + outb %al,$0x21 + pushl %esp + pushl $3 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_4 +_irq_handler_4: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<4,%al + outb %al,$0x21 + pushl %esp + pushl $4 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_5 +_irq_handler_5: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<5,%al + outb %al,$0x21 + pushl %esp + pushl $5 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_6 +_irq_handler_6: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<6,%al + outb %al,$0x21 + pushl %esp + pushl $6 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_7 +_irq_handler_7: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0x21,%al + orb $1<<7,%al + outb %al,$0x21 + pushl %esp + pushl $7 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_8 +_irq_handler_8: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(8-8),%al + outb %al,$0xa1 + pushl %esp + pushl $8 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_9 +_irq_handler_9: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(9-8),%al + outb %al,$0xa1 + pushl %esp + pushl $9 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_10 +_irq_handler_10: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(10-8),%al + outb %al,$0xa1 + pushl %esp + pushl $10 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_11 +_irq_handler_11: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(11-8),%al + outb %al,$0xa1 + pushl %esp + pushl $11 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_12 +_irq_handler_12: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(12-8),%al + outb %al,$0xa1 + pushl %esp + pushl $12 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_13 +_irq_handler_13: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(13-8),%al + outb %al,$0xa1 + pushl %esp + pushl $13 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_14 +_irq_handler_14: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(14-8),%al + outb %al,$0xa1 + pushl %esp + pushl $14 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + +.global _irq_handler_15 +_irq_handler_15: + pusha + pushl %ds + pushl %es + pushl %fs + movl $0xceafbeef,%eax + pushl %eax + movw $KERNEL_DS,%ax + movw %ax,%ds + movw %ax,%es + inb $0xa1,%al + orb $1<<(15-8),%al + outb %al,$0xa1 + pushl %esp + pushl $15 + call _KiInterruptDispatch + popl %eax + popl %eax + popl %eax + popl %fs + popl %es + popl %ds + popa + iret + + \ No newline at end of file diff --git a/reactos/ntoskrnl/mm/pageop.c b/reactos/ntoskrnl/mm/pageop.c new file mode 100644 index 00000000000..60e042faeb6 --- /dev/null +++ b/reactos/ntoskrnl/mm/pageop.c @@ -0,0 +1,164 @@ +/* $Id: pageop.c,v 1.1 2001/02/16 18:32:20 dwelch Exp $ + * + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS kernel + * FILE: ntoskrnl/mm/pageop.c + * PROGRAMMER: David Welch (welch@cwcom.net) + * UPDATE HISTORY: + * 27/05/98: Created + */ + +/* INCLUDES ****************************************************************/ + +#include +#include +#include +#include + +#define NDEBUG +#include + +/* GLOBALS *******************************************************************/ + +#define PAGEOP_HASH_TABLE_SIZE (32) + +KSPIN_LOCK MmPageOpHashTableLock; +PMM_PAGEOP MmPageOpHashTable[PAGEOP_HASH_TABLE_SIZE]; + +/* FUNCTIONS *****************************************************************/ + +VOID +MmReleasePageOp(PMM_PAGEOP PageOp) +{ + ULONG h; + KIRQL oldIrql; + PMM_PAGEOP PPageOp; + + PageOp->ReferenceCount--; + if (PageOp->ReferenceCount > 0) + { + return; + } + + /* + * Calcuate the hash value for pageop structure + */ + if (MArea->Type == MEMORY_AREA_SECTION_VIEW_COMMIT) + { + h = (((ULONG)Segment) | Offset) % PAGEOP_HASH_TABLE_SIZE; + } + else + { + h = (((ULONG)Pid) | (ULONG)Address) % PAGEOP_HASH_TABLE_SIZE; + } + + KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql); + PPageOp = MmPageOpHashTable[h]; + if (PPageOp == PageOp) + { + MmPageOpHashTable[h] = PageOp->Next; + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + ExFreePool(PageOp); + return; + } + PPageOp = PPageOp->Next; + while (PPageOp != NULL) + { + if (PPageOp == PageOp) + { + PPageOp->Next = PageOp->Next; + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + ExFreePool(PageOp); + return; + } + PPageOp = PPageOp->Next; + } + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + KeBugCheck(0); +} + +PMM_PAGEOP +MmGetPageOp(PMEMORY_AREA MArea, ULONG Pid, PVOID Address, + PMM_SECTION_SEGMENT Segment, ULONG Offset) +{ + ULONG h; + KIRQL oldIrql; + PMM_PAGEOP PageOp; + + /* + * Calcuate the hash value for pageop structure + */ + if (MArea->Type == MEMORY_AREA_SECTION_VIEW_COMMIT) + { + h = (((ULONG)Segment) | Offset) % PAGEOP_HASH_TABLE_SIZE; + } + else + { + h = (((ULONG)Pid) | (ULONG)Address) % PAGEOP_HASH_TABLE_SIZE; + } + + KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql); + + /* + * Check for an existing pageop structure + */ + PageOp = MmPageOpHashTable[h]; + while (PageOp != NULL) + { + if (MArea->Type == MEMORY_AREA_SECTION_VIEW_COMMIT) + { + if (PageOp->Segment == Segment && + PageOp->Offset == Offset) + { + break; + } + } + else + { + if (PageOp->Pid == Pid && + PageOp->Address == Address) + { + break; + } + } + PageOp = PageOp->Next; + } + + /* + * If we found an existing pageop then increment the reference count + * and return it. + */ + if (PageOp != NULL) + { + PageOp->ReferenceCount++; + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(PageOp); + } + + /* + * Otherwise add a new pageop. + */ + PageOp = ExAllocatePool(NonPagedPool, sizeof(MM_PAGEOP)); + if (PageOp == NULL) + { + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(NULL); + } + + if (MArea->Type == MEMORY_AREA_SECTION_VIEW_COMMIT) + { + PageOp->Pid = Pid; + PageOp->Address = Address; + } + else + { + PageOp->Segment = Segment; + PageOp->Offset = Offset; + } + PageOp->ReferenceCount = 1; + PageOp->Next = MmPageOpHashTable[h]; + MmPageOpHashTable[h] = PageOp; + + KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql); + return(PageOp); +}