* Release a wiring reference to a managed page. If the page still belongs to * an object, update its position in the page queues to reflect the reference. * If the wiring was the last reference to the page, free the page. */
| 3955 | * If the wiring was the last reference to the page, free the page. |
| 3956 | */ |
| 3957 | static void |
| 3958 | vm_page_unwire_managed(vm_page_t m, uint8_t nqueue, bool noreuse) |
| 3959 | { |
| 3960 | u_int old; |
| 3961 | |
| 3962 | KASSERT((m->oflags & VPO_UNMANAGED) == 0, |
| 3963 | ("%s: page %p is unmanaged", __func__, m)); |
| 3964 | |
| 3965 | /* |
| 3966 | * Update LRU state before releasing the wiring reference. |
| 3967 | * Use a release store when updating the reference count to |
| 3968 | * synchronize with vm_page_free_prep(). |
| 3969 | */ |
| 3970 | old = m->ref_count; |
| 3971 | do { |
| 3972 | KASSERT(VPRC_WIRE_COUNT(old) > 0, |
| 3973 | ("vm_page_unwire: wire count underflow for page %p", m)); |
| 3974 | |
| 3975 | if (old > VPRC_OBJREF + 1) { |
| 3976 | /* |
| 3977 | * The page has at least one other wiring reference. An |
| 3978 | * earlier iteration of this loop may have called |
| 3979 | * vm_page_release_toq() and cleared PGA_DEQUEUE, so |
| 3980 | * re-set it if necessary. |
| 3981 | */ |
| 3982 | if ((vm_page_astate_load(m).flags & PGA_DEQUEUE) == 0) |
| 3983 | vm_page_aflag_set(m, PGA_DEQUEUE); |
| 3984 | } else if (old == VPRC_OBJREF + 1) { |
| 3985 | /* |
| 3986 | * This is the last wiring. Clear PGA_DEQUEUE and |
| 3987 | * update the page's queue state to reflect the |
| 3988 | * reference. If the page does not belong to an object |
| 3989 | * (i.e., the VPRC_OBJREF bit is clear), we only need to |
| 3990 | * clear leftover queue state. |
| 3991 | */ |
| 3992 | vm_page_release_toq(m, nqueue, noreuse); |
| 3993 | } else if (old == 1) { |
| 3994 | vm_page_aflag_clear(m, PGA_DEQUEUE); |
| 3995 | } |
| 3996 | } while (!atomic_fcmpset_rel_int(&m->ref_count, &old, old - 1)); |
| 3997 | |
| 3998 | if (VPRC_WIRE_COUNT(old) == 1) { |
| 3999 | vm_wire_sub(1); |
| 4000 | if (old == 1) |
| 4001 | vm_page_free(m); |
| 4002 | } |
| 4003 | } |
| 4004 | |
| 4005 | /* |
| 4006 | * Release one wiring of the specified page, potentially allowing it to be |
no test coverage detected