Changeset View
Standalone View
sys/vm/vm_page.c
Show First 20 Lines • Show All 863 Lines • ▼ Show 20 Lines | |||||
void | void | ||||
vm_page_reference(vm_page_t m) | vm_page_reference(vm_page_t m) | ||||
{ | { | ||||
vm_page_aflag_set(m, PGA_REFERENCED); | vm_page_aflag_set(m, PGA_REFERENCED); | ||||
} | } | ||||
/* | /* | ||||
* vm_page_busy_acquire: | |||||
* | |||||
* Acquire the busy lock as described by VM_ALLOC_* flags. Will loop | |||||
* and drop the object lock if necessary. | |||||
*/ | |||||
int | |||||
vm_page_busy_acquire(vm_page_t m, int allocflags) | |||||
{ | |||||
vm_object_t obj; | |||||
bool locked; | |||||
/* | |||||
* The page-specific object must be cached because page | |||||
* identity can change during the sleep, causing the | |||||
* re-lock of a different object. | |||||
* It is assumed that a reference to the object is already | |||||
* held by the callers. | |||||
*/ | |||||
obj = m->object; | |||||
for (;;) { | |||||
if ((allocflags & VM_ALLOC_SBUSY) == 0) { | |||||
if (vm_page_tryxbusy(m)) | |||||
return (TRUE); | |||||
} else { | |||||
if (vm_page_trysbusy(m)) | |||||
return (TRUE); | |||||
} | |||||
if ((allocflags & VM_ALLOC_NOWAIT) != 0) | |||||
return (FALSE); | |||||
if (obj != NULL) | |||||
locked = VM_OBJECT_WOWNED(obj); | |||||
else | |||||
locked = FALSE; | |||||
if (locked) | |||||
VM_OBJECT_WUNLOCK(obj); | |||||
vm_page_busy_sleep(m, "pgbacq", (allocflags & | |||||
VM_ALLOC_SBUSY) != 0); | |||||
if (locked) | |||||
VM_OBJECT_WLOCK(obj); | |||||
if ((allocflags & VM_ALLOC_WAITFAIL) != 0) | |||||
return (FALSE); | |||||
} | |||||
} | |||||
/* | |||||
* vm_page_busy_downgrade: | * vm_page_busy_downgrade: | ||||
* | * | ||||
* Downgrade an exclusive busy page into a single shared busy page. | * Downgrade an exclusive busy page into a single shared busy page. | ||||
*/ | */ | ||||
void | void | ||||
vm_page_busy_downgrade(vm_page_t m) | vm_page_busy_downgrade(vm_page_t m) | ||||
{ | { | ||||
u_int x; | u_int x; | ||||
▲ Show 20 Lines • Show All 2,962 Lines • ▼ Show 20 Lines | if ((m = vm_page_lookup(object, pindex)) != NULL) { | ||||
if (sleep) { | if (sleep) { | ||||
if ((allocflags & VM_ALLOC_NOWAIT) != 0) | if ((allocflags & VM_ALLOC_NOWAIT) != 0) | ||||
return (NULL); | return (NULL); | ||||
/* | /* | ||||
* 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. | ||||
*/ | */ | ||||
if ((allocflags & VM_ALLOC_NOCREAT) != 0) | |||||
kib: Why do you changed the setting of PGA_REFERENCED ? | |||||
jeffAuthorUnsubmitted Done Inline ActionsI flipped this the wrong way. It should be NOCREAT == 0. Truncate, for example, wants to grab the last page to zero it, but only if it already exists. If not the pager will do it properly when it's created and you just waste time paging in an unnecessary page. jeff: I flipped this the wrong way. It should be NOCREAT == 0.
Truncate, for example, wants to grab… | |||||
jeffAuthorUnsubmitted Done Inline ActionsHow about ALLOC_IFVALID jeff: How about ALLOC_IFVALID | |||||
kibUnsubmitted Not Done Inline ActionsI still do not see why would we remove protection against pagedaemon during the sleep. We did found the page, so why NOCREAT/IFVALID should make it more likely for the page to be reclaimed under us, while we sleep for busy ? kib: I still do not see why would we remove protection against pagedaemon during the sleep. We did… | |||||
vm_page_aflag_set(m, PGA_REFERENCED); | vm_page_aflag_set(m, PGA_REFERENCED); | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
vm_page_busy_sleep(m, "pgrbwt", (allocflags & | vm_page_busy_sleep(m, "pgrbwt", (allocflags & | ||||
VM_ALLOC_IGN_SBUSY) != 0); | VM_ALLOC_IGN_SBUSY) != 0); | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
if ((allocflags & VM_ALLOC_WAITFAIL) != 0) | |||||
return (NULL); | |||||
goto retrylookup; | goto retrylookup; | ||||
} else { | } else { | ||||
if ((allocflags & VM_ALLOC_VALID) != 0 && | |||||
m->valid != VM_PAGE_BITS_ALL) | |||||
return (NULL); | |||||
if ((allocflags & VM_ALLOC_WIRED) != 0) { | if ((allocflags & VM_ALLOC_WIRED) != 0) { | ||||
vm_page_lock(m); | vm_page_lock(m); | ||||
vm_page_wire(m); | vm_page_wire(m); | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
} | } | ||||
if ((allocflags & | if ((allocflags & | ||||
(VM_ALLOC_NOBUSY | VM_ALLOC_SBUSY)) == 0) | (VM_ALLOC_NOBUSY | VM_ALLOC_SBUSY)) == 0) | ||||
vm_page_xbusy(m); | vm_page_xbusy(m); | ||||
if ((allocflags & VM_ALLOC_SBUSY) != 0) | else if ((allocflags & VM_ALLOC_SBUSY) != 0) | ||||
vm_page_sbusy(m); | vm_page_sbusy(m); | ||||
return (m); | return (m); | ||||
} | } | ||||
} | } | ||||
if ((allocflags & (VM_ALLOC_NOCREAT | VM_ALLOC_VALID)) != 0) | |||||
kibUnsubmitted Not Done Inline ActionsIt is somewhat strange semantic. If only ALLOC_VALID was specified, without ALLOC_NOCREAT, why zeroed page cannot satisfy the caller ? kib: It is somewhat strange semantic. If only ALLOC_VALID was specified, without ALLOC_NOCREAT, why… | |||||
jeffAuthorUnsubmitted Done Inline ActionsI overloaded the VALID name. I think we could use a different name for VM_ALLOC_VALID. It basically means, only return an existing valid page, but do no work to make it valid. There are some other weirdnesses. For example, vm_page_grab_pages() will set the page bits valid when it zeros a page. vm_page_grab() does not. I like this api layer that allows us to centralize synchronization but I feel at some point it could be simplified and split into a few smaller functions. The swiss army knife of flags always gets confusing. jeff: I overloaded the VALID name. I think we could use a different name for VM_ALLOC_VALID.
It… | |||||
kibUnsubmitted Not Done Inline ActionsI understand this, my point is that allocating a page is much more work than validate it by zeroing. kib: I understand this, my point is that allocating a page is much more work than validate it by… | |||||
return (NULL); | |||||
m = vm_page_alloc(object, pindex, pflags); | m = vm_page_alloc(object, pindex, pflags); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
if ((allocflags & VM_ALLOC_NOWAIT) != 0) | if ((allocflags & VM_ALLOC_NOWAIT) != 0) | ||||
return (NULL); | return (NULL); | ||||
goto retrylookup; | goto retrylookup; | ||||
} | } | ||||
if (allocflags & VM_ALLOC_ZERO && (m->flags & PG_ZERO) == 0) | if (allocflags & VM_ALLOC_ZERO && (m->flags & PG_ZERO) == 0) | ||||
pmap_zero_page(m); | pmap_zero_page(m); | ||||
▲ Show 20 Lines • Show All 162 Lines • ▼ Show 20 Lines | if (m != NULL) { | ||||
if (sleep) { | if (sleep) { | ||||
if ((allocflags & VM_ALLOC_NOWAIT) != 0) | if ((allocflags & VM_ALLOC_NOWAIT) != 0) | ||||
break; | break; | ||||
/* | /* | ||||
* 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. | ||||
*/ | */ | ||||
if ((allocflags & VM_ALLOC_NOCREAT) != 0) | |||||
vm_page_aflag_set(m, PGA_REFERENCED); | vm_page_aflag_set(m, PGA_REFERENCED); | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
vm_page_busy_sleep(m, "grbmaw", (allocflags & | vm_page_busy_sleep(m, "grbmaw", (allocflags & | ||||
VM_ALLOC_IGN_SBUSY) != 0); | VM_ALLOC_IGN_SBUSY) != 0); | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
goto retrylookup; | goto retrylookup; | ||||
} | } | ||||
if ((allocflags & VM_ALLOC_VALID) != 0 && !m->valid) | |||||
break; | |||||
if ((allocflags & VM_ALLOC_WIRED) != 0) { | if ((allocflags & VM_ALLOC_WIRED) != 0) { | ||||
vm_page_lock(m); | vm_page_lock(m); | ||||
vm_page_wire(m); | vm_page_wire(m); | ||||
vm_page_unlock(m); | vm_page_unlock(m); | ||||
} | } | ||||
if ((allocflags & (VM_ALLOC_NOBUSY | | if ((allocflags & (VM_ALLOC_NOBUSY | | ||||
VM_ALLOC_SBUSY)) == 0) | VM_ALLOC_SBUSY)) == 0) | ||||
vm_page_xbusy(m); | vm_page_xbusy(m); | ||||
if ((allocflags & VM_ALLOC_SBUSY) != 0) | if ((allocflags & VM_ALLOC_SBUSY) != 0) | ||||
vm_page_sbusy(m); | vm_page_sbusy(m); | ||||
} else { | } else { | ||||
if ((allocflags & | |||||
(VM_ALLOC_VALID | VM_ALLOC_NOCREAT)) != 0) | |||||
break; | |||||
m = vm_page_alloc_after(object, pindex + i, | m = vm_page_alloc_after(object, pindex + i, | ||||
pflags | VM_ALLOC_COUNT(count - i), mpred); | pflags | VM_ALLOC_COUNT(count - i), mpred); | ||||
if (m == NULL) { | if (m == NULL) { | ||||
if ((allocflags & VM_ALLOC_NOWAIT) != 0) | if ((allocflags & VM_ALLOC_NOWAIT) != 0) | ||||
break; | break; | ||||
goto retrylookup; | goto retrylookup; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 521 Lines • Show Last 20 Lines |
Why do you changed the setting of PGA_REFERENCED ?