Changeset View
Changeset View
Standalone View
Standalone View
head/sys/vm/vm_object.c
Show First 20 Lines • Show All 1,154 Lines • ▼ Show 20 Lines | if (tm->valid != VM_PAGE_BITS_ALL || | ||||
vm_page_wired(tm)) | vm_page_wired(tm)) | ||||
goto next_pindex; | goto next_pindex; | ||||
KASSERT((tm->flags & PG_FICTITIOUS) == 0, | KASSERT((tm->flags & PG_FICTITIOUS) == 0, | ||||
("vm_object_madvise: page %p is fictitious", tm)); | ("vm_object_madvise: page %p is fictitious", tm)); | ||||
KASSERT((tm->oflags & VPO_UNMANAGED) == 0, | KASSERT((tm->oflags & VPO_UNMANAGED) == 0, | ||||
("vm_object_madvise: page %p is not managed", tm)); | ("vm_object_madvise: page %p is not managed", tm)); | ||||
if (vm_page_busied(tm)) { | if (vm_page_busied(tm)) { | ||||
if (object != tobject) | if (object != tobject) | ||||
VM_OBJECT_WUNLOCK(tobject); | |||||
vm_page_lock(tm); | |||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
if (advice == MADV_WILLNEED) { | if (advice == MADV_WILLNEED) { | ||||
/* | /* | ||||
* Reference the page before unlocking and | * Reference the page before unlocking and | ||||
* sleeping so that the page daemon is less | * sleeping so that the page daemon is less | ||||
* likely to reclaim it. | * likely to reclaim it. | ||||
*/ | */ | ||||
vm_page_aflag_set(tm, PGA_REFERENCED); | vm_page_aflag_set(tm, PGA_REFERENCED); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 166 Lines • ▼ Show 20 Lines | for (; m != NULL && (idx = m->pindex - offidxstart) < size; | ||||
* We must wait for pending I/O to complete before we can | * We must wait for pending I/O to complete before we can | ||||
* rename the page. | * rename the page. | ||||
* | * | ||||
* We do not have to VM_PROT_NONE the page as mappings should | * We do not have to VM_PROT_NONE the page as mappings should | ||||
* not be changed by this operation. | * not be changed by this operation. | ||||
*/ | */ | ||||
if (vm_page_busied(m)) { | if (vm_page_busied(m)) { | ||||
VM_OBJECT_WUNLOCK(new_object); | VM_OBJECT_WUNLOCK(new_object); | ||||
vm_page_lock(m); | vm_page_sleep_if_busy(m, "spltwt"); | ||||
VM_OBJECT_WUNLOCK(orig_object); | |||||
vm_page_busy_sleep(m, "spltwt", false); | |||||
VM_OBJECT_WLOCK(orig_object); | |||||
VM_OBJECT_WLOCK(new_object); | VM_OBJECT_WLOCK(new_object); | ||||
goto retry; | goto retry; | ||||
} | } | ||||
/* vm_page_rename() will dirty the page. */ | /* vm_page_rename() will dirty the page. */ | ||||
if (vm_page_rename(m, new_object, idx)) { | if (vm_page_rename(m, new_object, idx)) { | ||||
VM_OBJECT_WUNLOCK(new_object); | VM_OBJECT_WUNLOCK(new_object); | ||||
VM_OBJECT_WUNLOCK(orig_object); | VM_OBJECT_WUNLOCK(orig_object); | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | vm_object_collapse_scan_wait(vm_object_t object, vm_page_t p, vm_page_t next, | ||||
backing_object = object->backing_object; | backing_object = object->backing_object; | ||||
VM_OBJECT_ASSERT_WLOCKED(backing_object); | VM_OBJECT_ASSERT_WLOCKED(backing_object); | ||||
KASSERT(p == NULL || vm_page_busied(p), ("unbusy page %p", p)); | KASSERT(p == NULL || vm_page_busied(p), ("unbusy page %p", p)); | ||||
KASSERT(p == NULL || p->object == object || p->object == backing_object, | KASSERT(p == NULL || p->object == object || p->object == backing_object, | ||||
("invalid ownership %p %p %p", p, object, backing_object)); | ("invalid ownership %p %p %p", p, object, backing_object)); | ||||
if ((op & OBSC_COLLAPSE_NOWAIT) != 0) | if ((op & OBSC_COLLAPSE_NOWAIT) != 0) | ||||
return (next); | return (next); | ||||
if (p != NULL) | |||||
vm_page_lock(p); | |||||
VM_OBJECT_WUNLOCK(object); | |||||
VM_OBJECT_WUNLOCK(backing_object); | |||||
/* The page is only NULL when rename fails. */ | /* The page is only NULL when rename fails. */ | ||||
if (p == NULL) | if (p == NULL) { | ||||
vm_radix_wait(); | vm_radix_wait(); | ||||
} else { | |||||
if (p->object == object) | |||||
VM_OBJECT_WUNLOCK(backing_object); | |||||
else | else | ||||
VM_OBJECT_WUNLOCK(object); | |||||
vm_page_busy_sleep(p, "vmocol", false); | vm_page_busy_sleep(p, "vmocol", false); | ||||
} | |||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
VM_OBJECT_WLOCK(backing_object); | VM_OBJECT_WLOCK(backing_object); | ||||
return (TAILQ_FIRST(&backing_object->memq)); | return (TAILQ_FIRST(&backing_object->memq)); | ||||
} | } | ||||
static bool | static bool | ||||
vm_object_scan_all_shadowed(vm_object_t object) | vm_object_scan_all_shadowed(vm_object_t object) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 397 Lines • ▼ Show 20 Lines | |||||
* | * | ||||
* The object must be locked. | * The object must be locked. | ||||
*/ | */ | ||||
void | void | ||||
vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, | vm_object_page_remove(vm_object_t object, vm_pindex_t start, vm_pindex_t end, | ||||
int options) | int options) | ||||
{ | { | ||||
vm_page_t p, next; | vm_page_t p, next; | ||||
struct mtx *mtx; | |||||
VM_OBJECT_ASSERT_WLOCKED(object); | VM_OBJECT_ASSERT_WLOCKED(object); | ||||
KASSERT((object->flags & OBJ_UNMANAGED) == 0 || | KASSERT((object->flags & OBJ_UNMANAGED) == 0 || | ||||
(options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED, | (options & (OBJPR_CLEANONLY | OBJPR_NOTMAPPED)) == OBJPR_NOTMAPPED, | ||||
("vm_object_page_remove: illegal options for object %p", object)); | ("vm_object_page_remove: illegal options for object %p", object)); | ||||
if (object->resident_page_count == 0) | if (object->resident_page_count == 0) | ||||
return; | return; | ||||
vm_object_pip_add(object, 1); | vm_object_pip_add(object, 1); | ||||
again: | again: | ||||
p = vm_page_find_least(object, start); | p = vm_page_find_least(object, start); | ||||
mtx = NULL; | |||||
/* | /* | ||||
* Here, the variable "p" is either (1) the page with the least pindex | * Here, the variable "p" is either (1) the page with the least pindex | ||||
* greater than or equal to the parameter "start" or (2) NULL. | * greater than or equal to the parameter "start" or (2) NULL. | ||||
*/ | */ | ||||
for (; p != NULL && (p->pindex < end || end == 0); p = next) { | for (; p != NULL && (p->pindex < end || end == 0); p = next) { | ||||
next = TAILQ_NEXT(p, listq); | next = TAILQ_NEXT(p, listq); | ||||
/* | /* | ||||
* If the page is wired for any reason besides the existence | * If the page is wired for any reason besides the existence | ||||
* of managed, wired mappings, then it cannot be freed. For | * of managed, wired mappings, then it cannot be freed. For | ||||
* example, fictitious pages, which represent device memory, | * example, fictitious pages, which represent device memory, | ||||
* are inherently wired and cannot be freed. They can, | * are inherently wired and cannot be freed. They can, | ||||
* however, be invalidated if the option OBJPR_CLEANONLY is | * however, be invalidated if the option OBJPR_CLEANONLY is | ||||
* not specified. | * not specified. | ||||
*/ | */ | ||||
vm_page_change_lock(p, &mtx); | |||||
if (vm_page_xbusied(p)) { | |||||
VM_OBJECT_WUNLOCK(object); | |||||
vm_page_busy_sleep(p, "vmopax", true); | |||||
VM_OBJECT_WLOCK(object); | |||||
goto again; | |||||
} | |||||
if (vm_page_busied(p)) { | if (vm_page_busied(p)) { | ||||
VM_OBJECT_WUNLOCK(object); | vm_page_sleep_if_busy(p, "vmopar"); | ||||
vm_page_busy_sleep(p, "vmopar", false); | |||||
VM_OBJECT_WLOCK(object); | |||||
goto again; | goto again; | ||||
} | } | ||||
if (vm_page_wired(p)) { | if (vm_page_wired(p)) { | ||||
wired: | wired: | ||||
if ((options & OBJPR_NOTMAPPED) == 0 && | if ((options & OBJPR_NOTMAPPED) == 0 && | ||||
object->ref_count != 0) | object->ref_count != 0) | ||||
pmap_remove_all(p); | pmap_remove_all(p); | ||||
if ((options & OBJPR_CLEANONLY) == 0) { | if ((options & OBJPR_CLEANONLY) == 0) { | ||||
Show All 12 Lines | if ((options & OBJPR_CLEANONLY) != 0 && p->valid != 0) { | ||||
if (p->dirty != 0) | if (p->dirty != 0) | ||||
continue; | continue; | ||||
} | } | ||||
if ((options & OBJPR_NOTMAPPED) == 0 && | if ((options & OBJPR_NOTMAPPED) == 0 && | ||||
object->ref_count != 0 && !vm_page_try_remove_all(p)) | object->ref_count != 0 && !vm_page_try_remove_all(p)) | ||||
goto wired; | goto wired; | ||||
vm_page_free(p); | vm_page_free(p); | ||||
} | } | ||||
if (mtx != NULL) | |||||
mtx_unlock(mtx); | |||||
vm_object_pip_wakeup(object); | vm_object_pip_wakeup(object); | ||||
} | } | ||||
/* | /* | ||||
* vm_object_page_noreuse: | * vm_object_page_noreuse: | ||||
* | * | ||||
* For the given object, attempt to move the specified pages to | * For the given object, attempt to move the specified pages to | ||||
* the head of the inactive queue. This bypasses regular LRU | * the head of the inactive queue. This bypasses regular LRU | ||||
▲ Show 20 Lines • Show All 268 Lines • ▼ Show 20 Lines | if (m == NULL || pindex < m->pindex) { | ||||
} | } | ||||
} while ((tm = vm_page_lookup(tobject, tpindex)) == | } while ((tm = vm_page_lookup(tobject, tpindex)) == | ||||
NULL); | NULL); | ||||
} else { | } else { | ||||
tm = m; | tm = m; | ||||
m = TAILQ_NEXT(m, listq); | m = TAILQ_NEXT(m, listq); | ||||
} | } | ||||
if (vm_page_xbusied(tm)) { | if (vm_page_xbusied(tm)) { | ||||
vm_page_lock(tm); | for (tobject = object; locked_depth > 1; | ||||
for (tobject = object; locked_depth >= 1; | |||||
locked_depth--) { | locked_depth--) { | ||||
t1object = tobject->backing_object; | t1object = tobject->backing_object; | ||||
VM_OBJECT_RUNLOCK(tobject); | VM_OBJECT_RUNLOCK(tobject); | ||||
tobject = t1object; | tobject = t1object; | ||||
} | } | ||||
vm_page_busy_sleep(tm, "unwbo", true); | vm_page_busy_sleep(tm, "unwbo", true); | ||||
goto again; | goto again; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 417 Lines • Show Last 20 Lines |