Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_page.c
Show First 20 Lines • Show All 2,646 Lines • ▼ Show 20 Lines | |||||
/* | /* | ||||
* vm_wait: (also see VM_WAIT macro) | * vm_wait: (also see VM_WAIT macro) | ||||
* | * | ||||
* Sleep until free pages are available for allocation. | * Sleep until free pages are available for allocation. | ||||
* - Called in various places before memory allocations. | * - Called in various places before memory allocations. | ||||
*/ | */ | ||||
static void | static void | ||||
_vm_wait(void) | _vm_wait(int timo) | ||||
{ | { | ||||
mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); | mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); | ||||
if (curproc == pageproc) { | if (curproc == pageproc) { | ||||
vm_pageout_pages_needed = 1; | vm_pageout_pages_needed = 1; | ||||
msleep(&vm_pageout_pages_needed, &vm_page_queue_free_mtx, | msleep(&vm_pageout_pages_needed, &vm_page_queue_free_mtx, | ||||
PDROP | PSWP, "VMWait", 0); | PDROP | PSWP, "VMWait", 0); | ||||
} else { | } else { | ||||
if (pageproc == NULL) | if (pageproc == NULL) | ||||
panic("vm_wait in early boot"); | panic("vm_wait in early boot"); | ||||
pagedaemon_wait(PVM, "vmwait"); | pagedaemon_wait(PVM, "vmwait", timo); | ||||
} | } | ||||
} | } | ||||
void | void | ||||
vm_wait(void) | vm_wait(int timo) | ||||
{ | { | ||||
mtx_lock(&vm_page_queue_free_mtx); | mtx_lock(&vm_page_queue_free_mtx); | ||||
_vm_wait(); | _vm_wait(timo); | ||||
} | } | ||||
/* | /* | ||||
* vm_page_alloc_fail: | * vm_page_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 | ||||
* page_queue_free and object lock on entry. Returns with the | * page_queue_free and object lock on entry. Returns with the | ||||
* object lock held and free lock released. Returns an error when | * object lock held and free lock released. Returns an error when | ||||
* retry is necessary. | * retry is necessary. | ||||
* | * | ||||
*/ | */ | ||||
static int | static int | ||||
vm_page_alloc_fail(vm_object_t object, int req) | vm_page_alloc_fail(vm_object_t object, int req) | ||||
{ | { | ||||
mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); | mtx_assert(&vm_page_queue_free_mtx, MA_OWNED); | ||||
atomic_add_int(&vm_pageout_deficit, | atomic_add_int(&vm_pageout_deficit, | ||||
max((u_int)req >> VM_ALLOC_COUNT_SHIFT, 1)); | max((u_int)req >> VM_ALLOC_COUNT_SHIFT, 1)); | ||||
if (req & (VM_ALLOC_WAITOK | VM_ALLOC_WAITFAIL)) { | if (req & (VM_ALLOC_WAITOK | VM_ALLOC_WAITFAIL)) { | ||||
if (object != NULL) | if (object != NULL) | ||||
VM_OBJECT_WUNLOCK(object); | VM_OBJECT_WUNLOCK(object); | ||||
_vm_wait(); | _vm_wait(0); | ||||
if (object != NULL) | if (object != NULL) | ||||
VM_OBJECT_WLOCK(object); | VM_OBJECT_WLOCK(object); | ||||
if (req & VM_ALLOC_WAITOK) | if (req & VM_ALLOC_WAITOK) | ||||
return (EAGAIN); | return (EAGAIN); | ||||
} else { | } else { | ||||
mtx_unlock(&vm_page_queue_free_mtx); | mtx_unlock(&vm_page_queue_free_mtx); | ||||
pagedaemon_wakeup(); | pagedaemon_wakeup(); | ||||
} | } | ||||
return (0); | return (0); | ||||
} | } | ||||
/* | /* | ||||
* vm_waitpfault: (also see VM_WAITPFAULT macro) | * vm_waitpfault: (also see VM_WAITPFAULT macro) | ||||
* | * | ||||
* Sleep until free pages are available for allocation. | * Sleep until free pages are available for allocation. | ||||
markj: "until free pages are available for allocation, or the requested timeout has elapsed." | |||||
* - Called only in vm_fault so that processes page faulting | * - Called only in vm_fault so that processes page faulting | ||||
* can be easily tracked. | * can be easily tracked. | ||||
Not Done Inline ActionsGiven that this function is defined to have only one caller, vm_fault(), couldn't we pass PCATCH to the msleep() call? alc: Given that this function is defined to have only one caller, vm_fault(), couldn't we pass… | |||||
Done Inline ActionsSo what would be the semantic ? We allow the sleep interruption with PCATCH, but the signal cannot be delivered right now so it is queued for the process. I do not see a way to interrupt the page fault handler, we either should fail it or restart. So the signal sent would just cause the earlier restart of the fault handler loop ? IMO timeout is enough for that. kib: So what would be the semantic ? We allow the sleep interruption with PCATCH, but the signal… | |||||
* - Sleeps at a lower priority than vm_wait() so that vm_wait()ing | * - Sleeps at a lower priority than vm_wait() so that vm_wait()ing | ||||
* processes will be able to grab memory first. Do not change | * processes will be able to grab memory first. Do not change | ||||
* this balance without careful testing first. | * this balance without careful testing first. | ||||
*/ | */ | ||||
void | void | ||||
vm_waitpfault(void) | vm_waitpfault(int timo) | ||||
{ | { | ||||
mtx_lock(&vm_page_queue_free_mtx); | mtx_lock(&vm_page_queue_free_mtx); | ||||
pagedaemon_wait(PUSER, "pfault"); | pagedaemon_wait(PUSER, "pfault", timo); | ||||
} | } | ||||
struct vm_pagequeue * | struct vm_pagequeue * | ||||
vm_page_pagequeue(vm_page_t m) | vm_page_pagequeue(vm_page_t m) | ||||
{ | { | ||||
if (vm_page_in_laundry(m)) | if (vm_page_in_laundry(m)) | ||||
return (&vm_dom[0].vmd_pagequeues[m->queue]); | return (&vm_dom[0].vmd_pagequeues[m->queue]); | ||||
▲ Show 20 Lines • Show All 1,261 Lines • Show Last 20 Lines |
"until free pages are available for allocation, or the requested timeout has elapsed."