Changeset View
Changeset View
Standalone View
Standalone View
sys/vm/vm_page.c
Show First 20 Lines • Show All 994 Lines • ▼ Show 20 Lines | for (;;) { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
/* | /* | ||||
* vm_page_busy_sleep: | * vm_page_busy_sleep: | ||||
* | * | ||||
* Sleep if the page is busy, using the page pointer as wchan. | * Sleep if the page is busy, using the page pointer as wchan. | ||||
* This is used to implement the hard-path of busying mechanism. | * This is used to implement the hard-path of the busying mechanism. | ||||
* | * | ||||
* If nonshared is true, sleep only if the page is xbusy. | * If VM_ALLOC_IGN_SBUSY is specified in allocflags, the function | ||||
* will not sleep if the page is shared-busy. | |||||
* | * | ||||
* The object lock must be held on entry and will be released on exit. | * The object lock must be held on entry. | ||||
* | |||||
* Returns true if it slept and dropped the object lock, or false | |||||
* if there was no sleep and the lock is still held. | |||||
*/ | */ | ||||
void | bool | ||||
vm_page_busy_sleep(vm_page_t m, const char *wmesg, bool nonshared) | vm_page_busy_sleep(vm_page_t m, const char *wmesg, int allocflags) | ||||
{ | { | ||||
vm_object_t obj; | vm_object_t obj; | ||||
obj = m->object; | obj = m->object; | ||||
VM_OBJECT_ASSERT_LOCKED(obj); | VM_OBJECT_ASSERT_LOCKED(obj); | ||||
vm_page_lock_assert(m, MA_NOTOWNED); | |||||
kib: It is somewhat strange API design.
Is it planned to allow other values for allocflags later on? | |||||
Done Inline ActionsI don't think there's any plan to permit other flags for now, but this way consumers use a standard terminology at least. I find it a bit nicer than a naked bool. I could simply remove the assertion. Note that _vm_page_busy_sleep() does not have any assertion since some other calls will pass vm_page_grab* flags in unmodified. markj: I don't think there's any plan to permit other flags for now, but this way consumers use a… | |||||
Done Inline ActionsTo me, removing the assertion looks reasonable. kib: To me, removing the assertion looks reasonable. | |||||
if (!_vm_page_busy_sleep(obj, m, m->pindex, wmesg, | return (_vm_page_busy_sleep(obj, m, m->pindex, wmesg, allocflags, | ||||
nonshared ? VM_ALLOC_SBUSY : 0 , true)) | true)); | ||||
VM_OBJECT_DROP(obj); | |||||
} | } | ||||
/* | /* | ||||
* vm_page_busy_sleep_unlocked: | * vm_page_busy_sleep_unlocked: | ||||
* | * | ||||
* Sleep if the page is busy, using the page pointer as wchan. | * Sleep if the page is busy, using the page pointer as wchan. | ||||
* This is used to implement the hard-path of busying mechanism. | * This is used to implement the hard-path of busying mechanism. | ||||
* | * | ||||
* If nonshared is true, sleep only if the page is xbusy. | * If VM_ALLOC_IGN_SBUSY is specified in allocflags, the function | ||||
* will not sleep if the page is shared-busy. | |||||
* | * | ||||
* The object lock must not be held on entry. The operation will | * The object lock must not be held on entry. The operation will | ||||
* return if the page changes identity. | * return if the page changes identity. | ||||
*/ | */ | ||||
void | void | ||||
vm_page_busy_sleep_unlocked(vm_object_t obj, vm_page_t m, vm_pindex_t pindex, | vm_page_busy_sleep_unlocked(vm_object_t obj, vm_page_t m, vm_pindex_t pindex, | ||||
const char *wmesg, bool nonshared) | const char *wmesg, int allocflags) | ||||
{ | { | ||||
VM_OBJECT_ASSERT_UNLOCKED(obj); | VM_OBJECT_ASSERT_UNLOCKED(obj); | ||||
vm_page_lock_assert(m, MA_NOTOWNED); | |||||
_vm_page_busy_sleep(obj, m, pindex, wmesg, | (void)_vm_page_busy_sleep(obj, m, pindex, wmesg, allocflags, false); | ||||
nonshared ? VM_ALLOC_SBUSY : 0, false); | |||||
} | } | ||||
/* | /* | ||||
* _vm_page_busy_sleep: | * _vm_page_busy_sleep: | ||||
* | * | ||||
* Internal busy sleep function. Verifies the page identity and | * Internal busy sleep function. Verifies the page identity and | ||||
* lockstate against parameters. Returns true if it sleeps and | * lockstate against parameters. Returns true if it sleeps and | ||||
* false otherwise. | * false otherwise. | ||||
* | * | ||||
* allocflags uses VM_ALLOC_* flags to specify the lock required. | |||||
* | |||||
* If locked is true the lock will be dropped for any true returns | * If locked is true the lock will be dropped for any true returns | ||||
* and held for any false returns. | * and held for any false returns. | ||||
*/ | */ | ||||
static bool | static bool | ||||
_vm_page_busy_sleep(vm_object_t obj, vm_page_t m, vm_pindex_t pindex, | _vm_page_busy_sleep(vm_object_t obj, vm_page_t m, vm_pindex_t pindex, | ||||
const char *wmesg, int allocflags, bool locked) | const char *wmesg, int allocflags, bool locked) | ||||
{ | { | ||||
bool xsleep; | bool xsleep; | ||||
▲ Show 20 Lines • Show All 327 Lines • ▼ Show 20 Lines | vm_page_free_invalid(vm_page_t m) | ||||
* If someone has wired this page while the object lock | * If someone has wired this page while the object lock | ||||
* was not held, then the thread that unwires is responsible | * was not held, then the thread that unwires is responsible | ||||
* for freeing the page. Otherwise just free the page now. | * for freeing the page. Otherwise just free the page now. | ||||
* The wire count of this unmapped page cannot change while | * The wire count of this unmapped page cannot change while | ||||
* we have the page xbusy and the page's object wlocked. | * we have the page xbusy and the page's object wlocked. | ||||
*/ | */ | ||||
if (vm_page_remove(m)) | if (vm_page_remove(m)) | ||||
vm_page_free(m); | vm_page_free(m); | ||||
} | |||||
/* | |||||
* vm_page_sleep_if_busy: | |||||
* | |||||
* Sleep and release the object lock if the page is busied. | |||||
* Returns TRUE if the thread slept. | |||||
* | |||||
* The given page must be unlocked and object containing it must | |||||
* be locked. | |||||
*/ | |||||
int | |||||
vm_page_sleep_if_busy(vm_page_t m, const char *wmesg) | |||||
{ | |||||
vm_object_t obj; | |||||
vm_page_lock_assert(m, MA_NOTOWNED); | |||||
VM_OBJECT_ASSERT_WLOCKED(m->object); | |||||
/* | |||||
* 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; | |||||
if (_vm_page_busy_sleep(obj, m, m->pindex, wmesg, 0, true)) { | |||||
VM_OBJECT_WLOCK(obj); | |||||
return (TRUE); | |||||
} | |||||
return (FALSE); | |||||
} | |||||
/* | |||||
* vm_page_sleep_if_xbusy: | |||||
* | |||||
* Sleep and release the object lock if the page is xbusied. | |||||
* Returns TRUE if the thread slept. | |||||
* | |||||
* The given page must be unlocked and object containing it must | |||||
* be locked. | |||||
*/ | |||||
int | |||||
vm_page_sleep_if_xbusy(vm_page_t m, const char *wmesg) | |||||
{ | |||||
vm_object_t obj; | |||||
vm_page_lock_assert(m, MA_NOTOWNED); | |||||
VM_OBJECT_ASSERT_WLOCKED(m->object); | |||||
/* | |||||
* 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; | |||||
if (_vm_page_busy_sleep(obj, m, m->pindex, wmesg, VM_ALLOC_SBUSY, | |||||
true)) { | |||||
VM_OBJECT_WLOCK(obj); | |||||
return (TRUE); | |||||
} | |||||
return (FALSE); | |||||
} | } | ||||
/* | /* | ||||
* vm_page_dirty_KBI: [ internal use only ] | * vm_page_dirty_KBI: [ internal use only ] | ||||
* | * | ||||
* Set all bits in the page's dirty field. | * Set all bits in the page's dirty field. | ||||
* | * | ||||
* The object containing the specified page must be locked if the | * The object containing the specified page must be locked if the | ||||
▲ Show 20 Lines • Show All 4,203 Lines • Show Last 20 Lines |
It is somewhat strange API design.
Is it planned to allow other values for allocflags later on?
If you decide to reuse allocflags there, why not allow any flags and just operate on the (allocflags & VM_ALLOC_IGN_SBUSY) != 0? Or not reuse and then make (keep) allocflags bool argunment.