首页
社区
课程
招聘
[旧帖] 有高手吗reactos的代码好像有错误,看我代码中的中文注释 0.00雪花
发表于: 2013-4-19 13:31 5130

[旧帖] 有高手吗reactos的代码好像有错误,看我代码中的中文注释 0.00雪花

2013-4-19 13:31
5130
reactos的代码好像有错误,看我代码中的绿色字体颜色的中文注释,相关代码已经全部在帖子中,请参考代码读我注释

NTSTATUS
NTAPI
MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
                             MEMORY_AREA* MemoryArea,
                             PVOID Address,
                             BOOLEAN Locked)
{
   ULONG Offset;
   PFN_TYPE Page;
   NTSTATUS Status;
   PVOID PAddress;
   PROS_SECTION_OBJECT Section;
   PMM_SECTION_SEGMENT Segment;
   ULONG Entry;
   ULONG Entry1;
   ULONG Attributes;
   PMM_PAGEOP PageOp;
   PMM_REGION Region;
   BOOLEAN HasSwapEntry;

   /*
    * There is a window between taking the page fault and locking the
    * address space when another thread could load the page so we check
    * that.
    */
   if (MmIsPagePresent(AddressSpace->Process, Address))
   {
      if (Locked)
      {
         MmLockPage(MmGetPfnForProcess(AddressSpace->Process, Address));
      }
      return(STATUS_SUCCESS);
   }

   PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
   Offset = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress
            + MemoryArea->Data.SectionData.ViewOffset;

   Segment = MemoryArea->Data.SectionData.Segment;
   Section = MemoryArea->Data.SectionData.Section;
   Region = MmFindRegion(MemoryArea->StartingAddress,
                         &MemoryArea->Data.SectionData.RegionListHead,
                         Address, NULL);
   /*
    * Lock the segment
    */
   MmLockSectionSegment(Segment);

   /*
    * Check if this page needs to be mapped COW
    */
   if ((Segment->WriteCopy || MemoryArea->Data.SectionData.WriteCopyView) &&
       (Region->Protect == PAGE_READWRITE ||
       Region->Protect == PAGE_EXECUTE_READWRITE))
   {
      Attributes = Region->Protect == PAGE_READWRITE ? PAGE_READONLY : PAGE_EXECUTE_READ;
   }
   else
   {
      Attributes = Region->Protect;
   }

   /*
    * Get or create a page operation descriptor
    */
PageOp = MmGetPageOp(MemoryArea, NULL, 0, Segment, Offset, MM_PAGEOP_PAGEIN, FALSE);// 假设这里获得的PageOp已经有一个线程在做PAGEOUT操作,根据帖子尾部的       MmGetPageOp假如有个线程在做页面操作(比如PAGEOUT)那么根据这个函数的最后1个参数是FALSE,那么这儿PageOp的引用计数加1,但是如果是页面换出操作(PAGEOUT)完成了,下面的MmspWaitForPageOpCompletionEvent(PageOp)等待的线程就会都向下运行,而PAGEOUT完成了,就会用帖子尾部的MmReleasePageOp释放PageOp(实际上就是减少引用计数,如果为0,则删除),如果有多个线程等待(多个线程获取了PageOp,引用计数累加)那么运行到下面的if (PageOp->OpType != MM_PAGEOP_PAGEIN)则会释放PageOp(减少引用计数)并return(STATUS_MM_RESTART_OPERATION);在帖子后面的MmNotPresentFault重新进入循环重新进行case MEMORY_AREA_SECTION_VIEW:
            Status = MmNotPresentFaultSectionView(AddressSpace,
                                                  MemoryArea,
                                                  (PVOID)Address,
                                                  Locked);
            break;重新进入MmNotPresentFaultSectionView,重新进入后又遇到MmGetPageOp又会获取PageOp(增加引用计数)这一增一减引用计数不是还没有变化吗,然后又在事件上等待,此时另一个线程运行到if (PageOp->OpType != MM_PAGEOP_PAGEIN),设置事件让等待的线程向下运行并释放PageOp(减少引用计数)然后又重新进入循环重新进入MmNotPresentFaultSectionView然后又获取PageOp(增加引用计数)这样的话不是PAGEOUT的pageOp永远没机会删除吗,这样永远没机会进行PAGE_IN操作了


   if (PageOp == NULL)
   {
      DPRINT1("MmGetPageOp failed\n");
      KEBUGCHECK(0);
   }

   /*
    * Check if someone else is already handling this fault, if so wait
    * for them
    */
   if (PageOp->Thread != PsGetCurrentThread())
   {
      MmUnlockSectionSegment(Segment);
      MmUnlockAddressSpace(AddressSpace);
      Status = MmspWaitForPageOpCompletionEvent(PageOp);//看上面注释,有多个线程等待PAGEOUT完成      /*
       * Check for various strange conditions
       */
      if (Status != STATUS_SUCCESS)
      {
         DPRINT1("Failed to wait for page op, status = %x\n", Status);
         KEBUGCHECK(0);
      }
      if (PageOp->Status == STATUS_PENDING)
      {
         DPRINT1("Woke for page op before completion\n");
         KEBUGCHECK(0);
      }
      MmLockAddressSpace(AddressSpace);
      /*
       * If this wasn't a pagein then restart the operation
       */
      if (PageOp->OpType != MM_PAGEOP_PAGEIN)//如果有正在处理的PageOP类型不是PAGEIIN
      {
         MmspCompleteAndReleasePageOp(PageOp);//则设置事件释放PAGEOP(减少引用计数)
         DPRINT("Address 0x%.8X\n", Address);
         return(STATUS_MM_RESTART_OPERATION);//返回上层MmNotPresentFault中重新循环运行到此:         case MEMORY_AREA_SECTION_VIEW:
            Status = MmNotPresentFaultSectionView(AddressSpace,
                                                  MemoryArea,
                                                  (PVOID)Address,
                                                  Locked);
            break;
      重新进入MmNotPresentFaultSectionView
     }
      /*
      * If the thread handling this fault has failed then we don't retry
      */
      if (!NT_SUCCESS(PageOp->Status))
      {
         Status = PageOp->Status;
         MmspCompleteAndReleasePageOp(PageOp);
         DPRINT("Address 0x%.8X\n", Address);
         return(Status);
      }
      MmLockSectionSegment(Segment);
      /*
       * If the completed fault was for another address space then set the
       * page in this one.
       */
      if (!MmIsPagePresent(AddressSpace->Process, Address))
      {
         Entry = MmGetPageEntrySectionSegment(Segment, Offset);
         HasSwapEntry = MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress);

         if (PAGE_FROM_SSE(Entry) == 0 || HasSwapEntry)
         {
            /*
             * The page was a private page in another or in our address space
             */
            MmUnlockSectionSegment(Segment);
            MmspCompleteAndReleasePageOp(PageOp);
            return(STATUS_MM_RESTART_OPERATION);
         }

         Page = PFN_FROM_SSE(Entry);

         MmSharePageEntrySectionSegment(Segment, Offset);

         /* FIXME: Should we call MmCreateVirtualMappingUnsafe if
          * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
          */
         Status = MmCreateVirtualMapping(AddressSpace->Process,
                                         Address,
                                         Attributes,
                                         &Page,
                                         1);
         if (!NT_SUCCESS(Status))
         {
            DPRINT1("Unable to create virtual mapping\n");
            KEBUGCHECK(0);
         }
         MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
      }
      if (Locked)
      {
         MmLockPage(Page);
      }
      MmUnlockSectionSegment(Segment);
      PageOp->Status = STATUS_SUCCESS;
      MmspCompleteAndReleasePageOp(PageOp);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }

   HasSwapEntry = MmIsPageSwapEntry(AddressSpace->Process, (PVOID)PAddress);
   if (HasSwapEntry)
   {
      /*
       * Must be private page we have swapped out.
       */
      SWAPENTRY SwapEntry;

      /*
       * Sanity check
       */
      if (Segment->Flags & MM_PAGEFILE_SEGMENT)
      {
         DPRINT1("Found a swaped out private page in a pagefile section.\n");
         KEBUGCHECK(0);
      }

      MmUnlockSectionSegment(Segment);
      MmDeletePageFileMapping(AddressSpace->Process, (PVOID)PAddress, &SwapEntry);

      MmUnlockAddressSpace(AddressSpace);
      Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
      if (!NT_SUCCESS(Status))
      {
         KEBUGCHECK(0);
      }

      Status = MmReadFromSwapPage(SwapEntry, Page);
      if (!NT_SUCCESS(Status))
      {
         DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
         KEBUGCHECK(0);
      }
      MmLockAddressSpace(AddressSpace);
      Status = MmCreateVirtualMapping(AddressSpace->Process,
                                      Address,
                                      Region->Protect,
                                      &Page,
                                      1);
      if (!NT_SUCCESS(Status))
      {
         DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
         KEBUGCHECK(0);
         return(Status);
      }

      /*
       * Store the swap entry for later use.
       */
      MmSetSavedSwapEntryPage(Page, SwapEntry);

      /*
       * Add the page to the process's working set
       */
      MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);

      /*
       * Finish the operation
       */
      if (Locked)
      {
         MmLockPage(Page);
      }
      PageOp->Status = STATUS_SUCCESS;
      MmspCompleteAndReleasePageOp(PageOp);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }

   /*
    * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
    */
   if (Section->AllocationAttributes & SEC_PHYSICALMEMORY)
   {
      MmUnlockSectionSegment(Segment);
      /*
       * Just map the desired physical page
       */
      Page = Offset >> PAGE_SHIFT;
      Status = MmCreateVirtualMappingUnsafe(AddressSpace->Process,
                                            Address,
                                            Region->Protect,
                                            &Page,
                                            1);
      if (!NT_SUCCESS(Status))
      {
         DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
         KEBUGCHECK(0);
         return(Status);
      }
      /*
       * Don't add an rmap entry since the page mapped could be for
       * anything.
       */
      if (Locked)
      {
         MmLockPageUnsafe(Page);
      }

      /*
       * Cleanup and release locks
       */
      PageOp->Status = STATUS_SUCCESS;
      MmspCompleteAndReleasePageOp(PageOp);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }

   /*
    * Map anonymous memory for BSS sections
    */
   if (Segment->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
   {
      MmUnlockSectionSegment(Segment);
      Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
      if (!NT_SUCCESS(Status))
      {
         MmUnlockAddressSpace(AddressSpace);
         Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
         MmLockAddressSpace(AddressSpace);
      }
      if (!NT_SUCCESS(Status))
      {
         KEBUGCHECK(0);
      }
      Status = MmCreateVirtualMapping(AddressSpace->Process,
                                      Address,
                                      Region->Protect,
                                      &Page,
                                      1);
      if (!NT_SUCCESS(Status))
      {
         DPRINT("MmCreateVirtualMapping failed, not out of memory\n");
         KEBUGCHECK(0);
         return(Status);
      }
      MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
      if (Locked)
      {
         MmLockPage(Page);
      }

      /*
       * Cleanup and release locks
       */
      PageOp->Status = STATUS_SUCCESS;
      MmspCompleteAndReleasePageOp(PageOp);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }

   /*
    * Get the entry corresponding to the offset within the section
    */
   Entry = MmGetPageEntrySectionSegment(Segment, Offset);

   if (Entry == 0)
   {
      /*
       * If the entry is zero (and it can't change because we have
       * locked the segment) then we need to load the page.
       */

      /*
       * Release all our locks and read in the page from disk
       */
      MmUnlockSectionSegment(Segment);
      MmUnlockAddressSpace(AddressSpace);

      if ((Segment->Flags & MM_PAGEFILE_SEGMENT) ||
          (Offset >= PAGE_ROUND_UP(Segment->RawLength) && Section->AllocationAttributes & SEC_IMAGE))
      {
         Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
         if (!NT_SUCCESS(Status))
         {
            DPRINT1("MmRequestPageMemoryConsumer failed (Status %x)\n", Status);
         }
      }
      else
      {
         Status = MiReadPage(MemoryArea, Offset, &Page);
         if (!NT_SUCCESS(Status))
         {
            DPRINT1("MiReadPage failed (Status %x)\n", Status);
         }
      }
      if (!NT_SUCCESS(Status))
      {
         /*
          * FIXME: What do we know in this case?
          */
         /*
          * Cleanup and release locks
          */
         MmLockAddressSpace(AddressSpace);
         PageOp->Status = Status;
         MmspCompleteAndReleasePageOp(PageOp);
         DPRINT("Address 0x%.8X\n", Address);
         return(Status);
      }
      /*
       * Relock the address space and segment
       */
      MmLockAddressSpace(AddressSpace);
      MmLockSectionSegment(Segment);

      /*
       * Check the entry. No one should change the status of a page
       * that has a pending page-in.
       */
      Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
      if (Entry != Entry1)
      {
         DPRINT1("Someone changed ppte entry while we slept\n");
         KEBUGCHECK(0);
      }

      /*
       * Mark the offset within the section as having valid, in-memory
       * data
       */
      Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
      MmSetPageEntrySectionSegment(Segment, Offset, Entry);
      MmUnlockSectionSegment(Segment);

      Status = MmCreateVirtualMapping(AddressSpace->Process,
                                      Address,
                                      Attributes,
                                      &Page,
                                      1);
      if (!NT_SUCCESS(Status))
      {
         DPRINT1("Unable to create virtual mapping\n");
         KEBUGCHECK(0);
      }
      MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);

      if (Locked)
      {
         MmLockPage(Page);
      }
      PageOp->Status = STATUS_SUCCESS;
      MmspCompleteAndReleasePageOp(PageOp);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
   else if (IS_SWAP_FROM_SSE(Entry))
   {
      SWAPENTRY SwapEntry;

      SwapEntry = SWAPENTRY_FROM_SSE(Entry);

      /*
      * Release all our locks and read in the page from disk
      */
      MmUnlockSectionSegment(Segment);

      MmUnlockAddressSpace(AddressSpace);

      Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
      if (!NT_SUCCESS(Status))
      {
         KEBUGCHECK(0);
      }

      Status = MmReadFromSwapPage(SwapEntry, Page);
      if (!NT_SUCCESS(Status))
      {
         KEBUGCHECK(0);
      }

      /*
       * Relock the address space and segment
       */
      MmLockAddressSpace(AddressSpace);
      MmLockSectionSegment(Segment);

      /*
       * Check the entry. No one should change the status of a page
       * that has a pending page-in.
       */
      Entry1 = MmGetPageEntrySectionSegment(Segment, Offset);
      if (Entry != Entry1)
      {
         DPRINT1("Someone changed ppte entry while we slept\n");
         KEBUGCHECK(0);
      }

      /*
       * Mark the offset within the section as having valid, in-memory
       * data
       */
      Entry = MAKE_SSE(Page << PAGE_SHIFT, 1);
      MmSetPageEntrySectionSegment(Segment, Offset, Entry);
      MmUnlockSectionSegment(Segment);

      /*
       * Save the swap entry.
       */
      MmSetSavedSwapEntryPage(Page, SwapEntry);
      Status = MmCreateVirtualMapping(AddressSpace->Process,
                                      Address,
                                      Region->Protect,
                                      &Page,
                                      1);
      if (!NT_SUCCESS(Status))
      {
         DPRINT1("Unable to create virtual mapping\n");
         KEBUGCHECK(0);
      }
      MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
      if (Locked)
      {
         MmLockPage(Page);
      }
      PageOp->Status = STATUS_SUCCESS;
      MmspCompleteAndReleasePageOp(PageOp);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
   else
   {
      /*
       * If the section offset is already in-memory and valid then just
       * take another reference to the page
       */

      Page = PFN_FROM_SSE(Entry);

      MmSharePageEntrySectionSegment(Segment, Offset);
      MmUnlockSectionSegment(Segment);

      Status = MmCreateVirtualMapping(AddressSpace->Process,
                                      Address,
                                      Attributes,
                                      &Page,
                                      1);
      if (!NT_SUCCESS(Status))
      {
         DPRINT1("Unable to create virtual mapping\n");
         KEBUGCHECK(0);
      }
      MmInsertRmap(Page, AddressSpace->Process, (PVOID)PAddress);
      if (Locked)
      {
         MmLockPage(Page);
      }
      PageOp->Status = STATUS_SUCCESS;
      MmspCompleteAndReleasePageOp(PageOp);
      DPRINT("Address 0x%.8X\n", Address);
      return(STATUS_SUCCESS);
   }
}

MmNotPresentFault(KPROCESSOR_MODE Mode,
                           ULONG_PTR Address,
                           BOOLEAN FromMdl)
{
   PMADDRESS_SPACE AddressSpace;
   MEMORY_AREA* MemoryArea;
   NTSTATUS Status;
   BOOLEAN Locked = FromMdl;
   PFN_TYPE Pfn;

   DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);

   if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
   {
      CPRINT("Page fault at high IRQL was %d, address %x\n", KeGetCurrentIrql(), Address);
      return(STATUS_UNSUCCESSFUL);
   }
   if (PsGetCurrentProcess() == NULL)
   {
      /* Allow this! It lets us page alloc much earlier! It won't be needed
       * after my init patch anyways
       */
      DPRINT("No current process\n");
      if (Address < (ULONG_PTR)MmSystemRangeStart)
      {
         return(STATUS_ACCESS_VIOLATION);
      }
   }

   /*
    * Find the memory area for the faulting address
    */
   if (Address >= (ULONG_PTR)MmSystemRangeStart)
   {
      /*
       * Check permissions
       */
      if (Mode != KernelMode)
      {
         CPRINT("Address: %x\n", Address);
         return(STATUS_ACCESS_VIOLATION);
      }
      AddressSpace = MmGetKernelAddressSpace();
   }
   else
   {
      AddressSpace = (PMADDRESS_SPACE)&(PsGetCurrentProcess())->VadRoot;
   }

   if (!FromMdl)
   {
      MmLockAddressSpace(AddressSpace);
   }

   /*
    * Call the memory area specific fault handler
    */
   do
   {
      MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
      if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
      {
         if (!FromMdl)
         {
            MmUnlockAddressSpace(AddressSpace);
         }
         return (STATUS_ACCESS_VIOLATION);
      }

      switch (MemoryArea->Type)
      {
         case MEMORY_AREA_PAGED_POOL:
            {
               Status = MmCommitPagedPoolAddress((PVOID)Address, Locked);
               break;
            }

         case MEMORY_AREA_SYSTEM:
            Status = STATUS_ACCESS_VIOLATION;
            break;

         case MEMORY_AREA_SECTION_VIEW:
            Status = MmNotPresentFaultSectionView(AddressSpace,
                                                  MemoryArea,
                                                  (PVOID)Address,
                                                  Locked);
            break;

         case MEMORY_AREA_VIRTUAL_MEMORY:
         case MEMORY_AREA_PEB_OR_TEB:
            Status = MmNotPresentFaultVirtualMemory(AddressSpace,
                                                    MemoryArea,
                                                    (PVOID)Address,
                                                    Locked);
            break;

         case MEMORY_AREA_SHARED_DATA:
            Pfn = MmSharedDataPagePhysicalAddress.LowPart >> PAGE_SHIFT;
            Status =
               MmCreateVirtualMapping(PsGetCurrentProcess(),
                                      (PVOID)PAGE_ROUND_DOWN(Address),
                                      PAGE_READONLY,
                                      &Pfn,
                                      1);
            break;

         default:
            Status = STATUS_ACCESS_VIOLATION;
            break;
      }
   }
   while (Status == STATUS_MM_RESTART_OPERATION);

   DPRINT("Completed page fault handling\n");
   if (!FromMdl)
   {
      MmUnlockAddressSpace(AddressSpace);
   }
   return(Status);
}

PMM_PAGEOP
NTAPI
MmGetPageOp(PMEMORY_AREA MArea, HANDLE Pid, PVOID Address,
            PMM_SECTION_SEGMENT Segment, ULONG Offset, ULONG OpType, BOOLEAN First)
/*
* FUNCTION: Get a page operation descriptor corresponding to
* the memory area and either the segment, offset pair or the
* pid, address pair.
*/
{
   ULONG_PTR Hash;
   KIRQL oldIrql;
   PMM_PAGEOP PageOp;

   if (!PageOpReady)
   {
       DPRINT1("PAGEOPS USED TOO SOON!!!\n");
       while (TRUE);
   }

   /*
    * Calcuate the hash value for pageop structure
    */
   if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
   {
      Hash = (((ULONG_PTR)Segment) | (((ULONG_PTR)Offset) / PAGE_SIZE));
   }
   else
   {
      Hash = (((ULONG_PTR)Pid) | (((ULONG_PTR)Address) / PAGE_SIZE));
   }
   Hash = Hash % PAGEOP_HASH_TABLE_SIZE;

   KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);

   /*
    * Check for an existing pageop structure
    */
   PageOp = MmPageOpHashTable[Hash];
   while (PageOp != NULL)
   {
      if (MArea->Type == MEMORY_AREA_SECTION_VIEW)
      {
         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)
   {
      if (First)
      {
         PageOp = NULL;
      }
      else
      {
         PageOp->ReferenceCount++;      }
      KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
      return(PageOp);
   }

   /*
    * Otherwise add a new pageop.
    */
   PageOp = ExAllocateFromNPagedLookasideList(&MmPageOpLookasideList);
   if (PageOp == NULL)
   {
      KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
      KEBUGCHECK(0);
      return(NULL);
   }

   if (MArea->Type != MEMORY_AREA_SECTION_VIEW)
   {
      PageOp->Pid = Pid;
      PageOp->Address = Address;
   }
   else
   {
      PageOp->Segment = Segment;
      PageOp->Offset = Offset;
   }
   PageOp->ReferenceCount = 1;
   PageOp->Next = MmPageOpHashTable[Hash];
   PageOp->Hash = Hash;
   PageOp->Thread = PsGetCurrentThread();
   PageOp->Abandoned = FALSE;
   PageOp->Status = STATUS_PENDING;
   PageOp->OpType = OpType;
   PageOp->MArea = MArea;
   KeInitializeEvent(&PageOp->CompletionEvent, NotificationEvent, FALSE);
   MmPageOpHashTable[Hash] = PageOp;
   (void)InterlockedIncrementUL(&MArea->PageOpCount);

   KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
   return(PageOp);
}

VOID
NTAPI
MmReleasePageOp(PMM_PAGEOP PageOp)
/*
* FUNCTION: Release a reference to a page operation descriptor
*/
{
   KIRQL oldIrql;
   PMM_PAGEOP PrevPageOp;

   KeAcquireSpinLock(&MmPageOpHashTableLock, &oldIrql);
   PageOp->ReferenceCount--;
   if (PageOp->ReferenceCount > 0)
   {
      KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
      return;
   }
   (void)InterlockedDecrementUL(&PageOp->MArea->PageOpCount);
   PrevPageOp = MmPageOpHashTable[PageOp->Hash];
   if (PrevPageOp == PageOp)
   {
      MmPageOpHashTable[PageOp->Hash] = PageOp->Next;
      KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
      ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
      return;
   }
   while (PrevPageOp->Next != NULL)
   {
      if (PrevPageOp->Next == PageOp)
      {
         PrevPageOp->Next = PageOp->Next;
         KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
         ExFreeToNPagedLookasideList(&MmPageOpLookasideList, PageOp);
         return;
      }
      PrevPageOp = PrevPageOp->Next;
   }
   KeReleaseSpinLock(&MmPageOpHashTableLock, oldIrql);
   KEBUGCHECK(0);
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (6)
雪    币: 8835
活跃值: (2404)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
2
和它的管理结构以及初始化有关,不能乱说有错~

毕竟和windows不一样~
2013-4-19 13:32
0
雪    币: 406
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
if (PageOp->Thread != PsGetCurrentThread())
2013-4-19 16:52
0
雪    币: 147
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
DuoLaMMeng兄,if (PageOp->Thread != PsGetCurrentThread())这个早就考虑过了,有页面操作的假设是换出操作,其他线程的都不是pageop初创时的线程,自然会到if里面等待PAGEOUT完成,我在代码中文注释里写的很清楚了
2013-4-20 11:56
0
雪    币: 228
活跃值: (115)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
5
if (PageOp->Thread != PsGetCurrentThread()) 其实并不重叠.具体原因.我也说不出为什么.

最好是虚拟机调试走起..
2013-4-24 23:12
0
雪    币: 55
活跃值: (519)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
6
放心吧,只要reactos能跑,错误也是可以原谅的
2013-4-25 09:32
0
雪    币: 406
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
PageOp->OpType 值等于 MM_PAGEOP_PAGEIN,没线程去改变。如何重新进入循环?
2013-4-25 10:28
0
游客
登录 | 注册 方可回帖
返回
//