Changeset View
Standalone View
sys/vm/vm_page.c
Show First 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | |||||
static int vm_page_insert_after(vm_page_t m, vm_object_t object, | static int vm_page_insert_after(vm_page_t m, vm_object_t object, | ||||
vm_pindex_t pindex, vm_page_t mpred); | vm_pindex_t pindex, vm_page_t mpred); | ||||
static void vm_page_insert_radixdone(vm_page_t m, vm_object_t object, | static void vm_page_insert_radixdone(vm_page_t m, vm_object_t object, | ||||
vm_page_t mpred); | vm_page_t mpred); | ||||
static int vm_page_reclaim_run(int req_class, int domain, u_long npages, | static int vm_page_reclaim_run(int req_class, int domain, u_long npages, | ||||
vm_page_t m_run, vm_paddr_t high); | vm_page_t m_run, vm_paddr_t high); | ||||
static int vm_domain_alloc_fail(struct vm_domain *vmd, vm_object_t object, | static int vm_domain_alloc_fail(struct vm_domain *vmd, vm_object_t object, | ||||
int req); | int req); | ||||
static int vm_page_zone_import(void *arg, void **store, int cnt, int domain, | static int vm_page_zone_import(void *arg, void **store, int cnt, int domain, | ||||
kib: Is this unrelated ? | |||||
Done Inline ActionsNo, I renamed the old (static) vm_page_release() to vm_page_zone_release(), and renamed vm_page_import() as well for consistency. markj: No, I renamed the old (static) vm_page_release() to vm_page_zone_release(), and renamed… | |||||
Not Done Inline ActionsI think it is useful to commit this part separately, and definitely merge it to 12. kib: I think it is useful to commit this part separately, and definitely merge it to 12. | |||||
int flags); | int flags); | ||||
static void vm_page_zone_release(void *arg, void **store, int cnt); | static void vm_page_zone_release(void *arg, void **store, int cnt); | ||||
SYSINIT(vm_page, SI_SUB_VM, SI_ORDER_SECOND, vm_page_init, NULL); | SYSINIT(vm_page, SI_SUB_VM, SI_ORDER_SECOND, vm_page_init, NULL); | ||||
static void | static void | ||||
vm_page_init(void *dummy) | vm_page_init(void *dummy) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 3,563 Lines • ▼ Show 20 Lines | vm_page_unswappable(vm_page_t m) | ||||
KASSERT(!vm_page_wired(m) && (m->oflags & VPO_UNMANAGED) == 0, | KASSERT(!vm_page_wired(m) && (m->oflags & VPO_UNMANAGED) == 0, | ||||
("page %p already unswappable", m)); | ("page %p already unswappable", m)); | ||||
vm_page_dequeue(m); | vm_page_dequeue(m); | ||||
vm_page_enqueue(m, PQ_UNSWAPPABLE); | vm_page_enqueue(m, PQ_UNSWAPPABLE); | ||||
} | } | ||||
/* | /* | ||||
* Attempt to free the page. If it cannot be freed, do nothing. Returns true | * Unwire a page and either attempt to free it or re-add it to the page queues. | ||||
* if the page is freed and false otherwise. | */ | ||||
void | |||||
vm_page_release(vm_page_t m, int flags) | |||||
{ | |||||
vm_object_t object; | |||||
bool freed; | |||||
dougmUnsubmitted Done Inline Actionsassert that m->object is not locked. dougm: assert that m->object is not locked. | |||||
markjAuthorUnsubmitted Done Inline ActionsNote that m->object may be NULL. I added the conditional assertion under the page lock, since the page lock is required in order to modify the object field. markj: Note that m->object may be NULL. I added the conditional assertion under the page lock, since… | |||||
KASSERT((m->oflags & VPO_UNMANAGED) == 0, | |||||
("vm_page_release: page %p is managed", m)); | |||||
Not Done Inline Actions"managed" -> "unmanaged" alc: "managed" -> "unmanaged" | |||||
vm_page_lock(m); | |||||
if (vm_page_unwire_noq(m)) { | |||||
if ((object = m->object) == NULL) { | |||||
vm_page_free(m); | |||||
} else { | |||||
freed = false; | |||||
if ((flags & VPR_TRYFREE) != 0 && !vm_page_busied(m) && | |||||
Not Done Inline ActionsWhat prevents other thread from busying the page after we tested for !xbusy but before TRYWLOCK() succeeded ? kib: What prevents other thread from busying the page after we tested for !xbusy but before TRYWLOCK… | |||||
Done Inline ActionsNothing, but there is a vm_page_busied(m) check after we acquire the object lock. This is identical to the logic in sendfile_free_page(). I accidentally removed a comment explaining that the first check is racy, I will restore it. markj: Nothing, but there is a `vm_page_busied(m)` check after we acquire the object lock. This is… | |||||
Not Done Inline ActionsThen why the first (racy) check is not vm_page_busied() ? kib: Then why the first (racy) check is not vm_page_busied() ? | |||||
VM_OBJECT_TRYWLOCK(object)) { | |||||
/* | |||||
* Only free unmapped pages. The busy test from | |||||
* before the object was locked cannot be relied | |||||
* upon. | |||||
*/ | |||||
if ((object->ref_count == 0 || | |||||
!pmap_page_is_mapped(m)) && m->dirty == 0 && | |||||
!vm_page_busied(m)) { | |||||
vm_page_free(m); | |||||
freed = true; | |||||
} | |||||
VM_OBJECT_WUNLOCK(object); | |||||
} | |||||
if (!freed) { | |||||
/* | |||||
* Use a racy check of the valid bits to | |||||
* determine whether we should accelerate | |||||
* reclamation of the page. At worst we will | |||||
* either accelerate reclamation of a valid page | |||||
* and violate LRU, or unnecessarily defer | |||||
* reclamation of an invalid page. | |||||
* | * | ||||
* The page must be managed. The page and its containing object must be | * If we were asked to not cache the page, place | ||||
* locked. | * it near the head of the inactive queue so | ||||
* that is reclaimed sooner. | |||||
*/ | */ | ||||
bool | if ((flags & (VPR_NOREUSE | VPR_TRYFREE)) != 0 || | ||||
dougmUnsubmitted Done Inline ActionsConsider defining these seven lines as a function of m and flags, and using it here and below. dougm: Consider defining these seven lines as a function of m and flags, and using it here and below. | |||||
vm_page_try_to_free(vm_page_t m) | m->valid == 0) | ||||
vm_page_deactivate_noreuse(m); | |||||
else if (vm_page_active(m)) | |||||
vm_page_reference(m); | |||||
else | |||||
vm_page_deactivate(m); | |||||
} | |||||
} | |||||
} | |||||
vm_page_unlock(m); | |||||
} | |||||
/* See vm_page_release(). */ | |||||
void | |||||
vm_page_release_locked(vm_page_t m, int flags) | |||||
{ | { | ||||
vm_page_assert_locked(m); | |||||
VM_OBJECT_ASSERT_WLOCKED(m->object); | VM_OBJECT_ASSERT_WLOCKED(m->object); | ||||
KASSERT((m->oflags & VPO_UNMANAGED) == 0, ("page %p is unmanaged", m)); | KASSERT((m->oflags & VPO_UNMANAGED) == 0, | ||||
if (m->dirty != 0 || vm_page_wired(m) || vm_page_busied(m)) | ("vm_page_release_locked: page %p is managed", m)); | ||||
Not Done Inline Actions"managed" -> "unmanaged" alc: "managed" -> "unmanaged" | |||||
return (false); | |||||
if (m->object->ref_count != 0) { | vm_page_lock(m); | ||||
pmap_remove_all(m); | if (vm_page_unwire_noq(m)) { | ||||
if (m->dirty != 0) | if ((flags & VPR_TRYFREE) != 0 && | ||||
return (false); | (m->object->ref_count == 0 || !pmap_page_is_mapped(m)) && | ||||
} | m->dirty == 0 && !vm_page_busied(m)) { | ||||
vm_page_free(m); | vm_page_free(m); | ||||
return (true); | } else { | ||||
if ((flags & (VPR_TRYFREE | VPR_NOREUSE)) != 0 || | |||||
m->valid == 0) | |||||
vm_page_deactivate_noreuse(m); | |||||
else if (vm_page_active(m)) | |||||
vm_page_reference(m); | |||||
else | |||||
vm_page_deactivate(m); | |||||
} | |||||
} | |||||
vm_page_unlock(m); | |||||
} | } | ||||
/* | /* | ||||
* vm_page_advise | * vm_page_advise | ||||
* | * | ||||
* Apply the specified advice to the given page. | * Apply the specified advice to the given page. | ||||
* | * | ||||
* The object and page must be locked. | * The object and page must be locked. | ||||
▲ Show 20 Lines • Show All 730 Lines • Show Last 20 Lines |
Is this unrelated ?