Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_page.c
Show First 20 Lines • Show All 3,111 Lines • ▼ Show 20 Lines | |||||
u_int | u_int | ||||
vm_wait_count(void) | vm_wait_count(void) | ||||
{ | { | ||||
return (vm_severe_waiters + vm_min_waiters + vm_pageproc_waiters); | return (vm_severe_waiters + vm_min_waiters + vm_pageproc_waiters); | ||||
} | } | ||||
void | int | ||||
vm_wait_doms(const domainset_t *wdoms) | vm_wait_doms(const domainset_t *wdoms, int mflags) | ||||
{ | { | ||||
int error; | |||||
error = 0; | |||||
/* | /* | ||||
* We use racey wakeup synchronization to avoid expensive global | * We use racey wakeup synchronization to avoid expensive global | ||||
* locking for the pageproc when sleeping with a non-specific vm_wait. | * locking for the pageproc when sleeping with a non-specific vm_wait. | ||||
* To handle this, we only sleep for one tick in this instance. It | * To handle this, we only sleep for one tick in this instance. It | ||||
* is expected that most allocations for the pageproc will come from | * is expected that most allocations for the pageproc will come from | ||||
* kmem or vm_page_grab* which will use the more specific and | * kmem or vm_page_grab* which will use the more specific and | ||||
* race-free vm_wait_domain(). | * race-free vm_wait_domain(). | ||||
*/ | */ | ||||
if (curproc == pageproc) { | if (curproc == pageproc) { | ||||
mtx_lock(&vm_domainset_lock); | mtx_lock(&vm_domainset_lock); | ||||
vm_pageproc_waiters++; | vm_pageproc_waiters++; | ||||
msleep(&vm_pageproc_waiters, &vm_domainset_lock, PVM | PDROP, | error = msleep(&vm_pageproc_waiters, &vm_domainset_lock, | ||||
"pageprocwait", 1); | PVM | PDROP | mflags, "pageprocwait", 1); | ||||
} else { | } else { | ||||
/* | /* | ||||
* XXX Ideally we would wait only until the allocation could | * XXX Ideally we would wait only until the allocation could | ||||
* be satisfied. This condition can cause new allocators to | * be satisfied. This condition can cause new allocators to | ||||
* consume all freed pages while old allocators wait. | * consume all freed pages while old allocators wait. | ||||
*/ | */ | ||||
mtx_lock(&vm_domainset_lock); | mtx_lock(&vm_domainset_lock); | ||||
if (vm_page_count_min_set(wdoms)) { | if (vm_page_count_min_set(wdoms)) { | ||||
vm_min_waiters++; | vm_min_waiters++; | ||||
msleep(&vm_min_domains, &vm_domainset_lock, | error = msleep(&vm_min_domains, &vm_domainset_lock, | ||||
PVM | PDROP, "vmwait", 0); | PVM | PDROP | mflags, "vmwait", 0); | ||||
} else | } else | ||||
mtx_unlock(&vm_domainset_lock); | mtx_unlock(&vm_domainset_lock); | ||||
} | } | ||||
return (error); | |||||
} | } | ||||
/* | /* | ||||
* vm_wait_domain: | * vm_wait_domain: | ||||
* | * | ||||
* Sleep until free pages are available for allocation. | * Sleep until free pages are available for allocation. | ||||
* - Called in various places after failed memory allocations. | * - Called in various places after failed memory allocations. | ||||
*/ | */ | ||||
Show All 14 Lines | if (vmd->vmd_free_count < vmd->vmd_pageout_free_min) { | ||||
&vm_domainset_lock, PDROP | PSWP, "VMWait", 0); | &vm_domainset_lock, PDROP | PSWP, "VMWait", 0); | ||||
} else | } else | ||||
mtx_unlock(&vm_domainset_lock); | mtx_unlock(&vm_domainset_lock); | ||||
} else { | } else { | ||||
if (pageproc == NULL) | if (pageproc == NULL) | ||||
panic("vm_wait in early boot"); | panic("vm_wait in early boot"); | ||||
DOMAINSET_ZERO(&wdom); | DOMAINSET_ZERO(&wdom); | ||||
DOMAINSET_SET(vmd->vmd_domain, &wdom); | DOMAINSET_SET(vmd->vmd_domain, &wdom); | ||||
vm_wait_doms(&wdom); | vm_wait_doms(&wdom, 0); | ||||
} | } | ||||
} | } | ||||
/* | static int | ||||
* vm_wait: | vm_wait_flags(vm_object_t obj, int mflags) | ||||
* | |||||
* Sleep until free pages are available for allocation in the | |||||
* affinity domains of the obj. If obj is NULL, the domain set | |||||
* for the calling thread is used. | |||||
* Called in various places after failed memory allocations. | |||||
*/ | |||||
void | |||||
vm_wait(vm_object_t obj) | |||||
{ | { | ||||
struct domainset *d; | struct domainset *d; | ||||
d = NULL; | d = NULL; | ||||
/* | /* | ||||
* Carefully fetch pointers only once: the struct domainset | * Carefully fetch pointers only once: the struct domainset | ||||
* itself is ummutable but the pointer might change. | * itself is ummutable but the pointer might change. | ||||
*/ | */ | ||||
if (obj != NULL) | if (obj != NULL) | ||||
d = obj->domain.dr_policy; | d = obj->domain.dr_policy; | ||||
if (d == NULL) | if (d == NULL) | ||||
d = curthread->td_domain.dr_policy; | d = curthread->td_domain.dr_policy; | ||||
vm_wait_doms(&d->ds_mask); | return (vm_wait_doms(&d->ds_mask, mflags)); | ||||
} | |||||
/* | |||||
* vm_wait: | |||||
* | |||||
* Sleep until free pages are available for allocation in the | |||||
* affinity domains of the obj. If obj is NULL, the domain set | |||||
* for the calling thread is used. | |||||
* Called in various places after failed memory allocations. | |||||
*/ | |||||
void | |||||
vm_wait(vm_object_t obj) | |||||
{ | |||||
(void)vm_wait_flags(obj, 0); | |||||
} | |||||
int | |||||
vm_wait_intr(vm_object_t obj) | |||||
{ | |||||
return (vm_wait_flags(obj, PCATCH)); | |||||
} | } | ||||
/* | /* | ||||
* vm_domain_alloc_fail: | * vm_domain_alloc_fail: | ||||
* | * | ||||
* Called when a page allocation function fails. Informs the | * Called when a page allocation function fails. Informs the | ||||
* pagedaemon and performs the requested wait. Requires the | * pagedaemon and performs the requested wait. Requires the | ||||
* domain_free and object lock on entry. Returns with the | * domain_free and object lock on entry. Returns with the | ||||
▲ Show 20 Lines • Show All 2,250 Lines • Show Last 20 Lines |