* vm_page_free_prep: * * Prepares the given page to be put on the free list, * disassociating it from any VM object. The caller may return * the page to the free list only if this function returns true. * * The object, if it exists, must be locked, and then the page must * be xbusy. Otherwise the page must be not busied. A managed * page must be unmapped. */
| 3739 | * page must be unmapped. |
| 3740 | */ |
| 3741 | static bool |
| 3742 | vm_page_free_prep(vm_page_t m) |
| 3743 | { |
| 3744 | |
| 3745 | /* |
| 3746 | * Synchronize with threads that have dropped a reference to this |
| 3747 | * page. |
| 3748 | */ |
| 3749 | atomic_thread_fence_acq(); |
| 3750 | |
| 3751 | #if defined(DIAGNOSTIC) && defined(PHYS_TO_DMAP) |
| 3752 | if (PMAP_HAS_DMAP && (m->flags & PG_ZERO) != 0) { |
| 3753 | uint64_t *p; |
| 3754 | int i; |
| 3755 | p = (uint64_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)); |
| 3756 | for (i = 0; i < PAGE_SIZE / sizeof(uint64_t); i++, p++) |
| 3757 | KASSERT(*p == 0, ("vm_page_free_prep %p PG_ZERO %d %jx", |
| 3758 | m, i, (uintmax_t)*p)); |
| 3759 | } |
| 3760 | #endif |
| 3761 | if ((m->oflags & VPO_UNMANAGED) == 0) { |
| 3762 | KASSERT(!pmap_page_is_mapped(m), |
| 3763 | ("vm_page_free_prep: freeing mapped page %p", m)); |
| 3764 | KASSERT((m->a.flags & (PGA_EXECUTABLE | PGA_WRITEABLE)) == 0, |
| 3765 | ("vm_page_free_prep: mapping flags set in page %p", m)); |
| 3766 | } else { |
| 3767 | KASSERT(m->a.queue == PQ_NONE, |
| 3768 | ("vm_page_free_prep: unmanaged page %p is queued", m)); |
| 3769 | } |
| 3770 | VM_CNT_INC(v_tfree); |
| 3771 | |
| 3772 | if (m->object != NULL) { |
| 3773 | KASSERT(((m->oflags & VPO_UNMANAGED) != 0) == |
| 3774 | ((m->object->flags & OBJ_UNMANAGED) != 0), |
| 3775 | ("vm_page_free_prep: managed flag mismatch for page %p", |
| 3776 | m)); |
| 3777 | vm_page_assert_xbusied(m); |
| 3778 | |
| 3779 | /* |
| 3780 | * The object reference can be released without an atomic |
| 3781 | * operation. |
| 3782 | */ |
| 3783 | KASSERT((m->flags & PG_FICTITIOUS) != 0 || |
| 3784 | m->ref_count == VPRC_OBJREF, |
| 3785 | ("vm_page_free_prep: page %p has unexpected ref_count %u", |
| 3786 | m, m->ref_count)); |
| 3787 | vm_page_object_remove(m); |
| 3788 | m->ref_count -= VPRC_OBJREF; |
| 3789 | } else |
| 3790 | vm_page_assert_unbusied(m); |
| 3791 | |
| 3792 | vm_page_busy_free(m); |
| 3793 | |
| 3794 | /* |
| 3795 | * If fictitious remove object association and |
| 3796 | * return. |
| 3797 | */ |
| 3798 | if ((m->flags & PG_FICTITIOUS) != 0) { |
no test coverage detected