* vm_object_page_remove: * * For the given object, either frees or invalidates each of the * specified pages. In general, a page is freed. However, if a page is * wired for any reason other than the existence of a managed, wired * mapping, then it may be invalidated but not removed from the object. * Pages are specified by the given range ["start", "end") and the option * OBJPR_CLEANONLY.
| 2071 | * The object must be locked. |
| 2072 | */ |
| 2073 | void |
| 2074 | vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, |
| 2075 | int options) |
| 2076 | { |
| 2077 | vm_page_t p, next; |
| 2078 | |
| 2079 | VM_OBJECT_ASSERT_WLOCKED(object); |
| 2080 | KASSERT((object->flags & OBJ_UNMANAGED) == 0 || |
| 2081 | (options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED, |
| 2082 | ("vm_object_page_remove: illegal options for object %p", object)); |
| 2083 | if (object->resident_page_count == 0) |
| 2084 | return; |
| 2085 | vm_object_pip_add(object, 1); |
| 2086 | again: |
| 2087 | p = vm_page_find_least(object, start); |
| 2088 | |
| 2089 | /* |
| 2090 | * Here, the variable "p" is either (1) the page with the least pindex |
| 2091 | * greater than or equal to the parameter "start" or (2) NULL. |
| 2092 | */ |
| 2093 | for (; p != NULL && (p->pindex < end || end == 0); p = next) { |
| 2094 | next = TAILQ_NEXT(p, listq); |
| 2095 | |
| 2096 | /* |
| 2097 | * If the page is wired for any reason besides the existence |
| 2098 | * of managed, wired mappings, then it cannot be freed. For |
| 2099 | * example, fictitious pages, which represent device memory, |
| 2100 | * are inherently wired and cannot be freed. They can, |
| 2101 | * however, be invalidated if the option OBJPR_CLEANONLY is |
| 2102 | * not specified. |
| 2103 | */ |
| 2104 | if (vm_page_tryxbusy(p) == 0) { |
| 2105 | vm_page_sleep_if_busy(p, "vmopar"); |
| 2106 | goto again; |
| 2107 | } |
| 2108 | if (vm_page_wired(p)) { |
| 2109 | wired: |
| 2110 | if ((options & OBJPR_NOTMAPPED) == 0 && |
| 2111 | object->ref_count != 0) |
| 2112 | pmap_remove_all(p); |
| 2113 | if ((options & OBJPR_CLEANONLY) == 0) { |
| 2114 | vm_page_invalid(p); |
| 2115 | vm_page_undirty(p); |
| 2116 | } |
| 2117 | vm_page_xunbusy(p); |
| 2118 | continue; |
| 2119 | } |
| 2120 | KASSERT((p->flags & PG_FICTITIOUS) == 0, |
| 2121 | ("vm_object_page_remove: page %p is fictitious", p)); |
| 2122 | if ((options & OBJPR_CLEANONLY) != 0 && |
| 2123 | !vm_page_none_valid(p)) { |
| 2124 | if ((options & OBJPR_NOTMAPPED) == 0 && |
| 2125 | object->ref_count != 0 && |
| 2126 | !vm_page_try_remove_write(p)) |
| 2127 | goto wired; |
| 2128 | if (p->dirty != 0) { |
| 2129 | vm_page_xunbusy(p); |
| 2130 | continue; |
no test coverage detected