VM_PAGE_BUSY(9)

πŸ’– VM_PAGE_BUSY(9) πŸ’–

okay bestie, welcome to the Kernel Developer's Manual section 9, page VM_PAGE_BUSY β€” this is the page about protecting page identity changes and page content references. yes it's giving very serious kernel business and yes i'm gonna make it make sense. πŸ¦‹


✨ NAME ✨

vm_page_busied, vm_page_busy_downgrade, vm_page_busy_sleep, vm_page_sbusied, vm_page_sbusy, vm_page_sleep_if_busy, vm_page_sunbusy, vm_page_trysbusy, vm_page_tryxbusy, vm_page_xbusied, vm_page_xbusy, vm_page_xunbusy, vm_page_assert_sbusied, vm_page_assert_unbusied, vm_page_assert_xbusied β€” protect page identity changes and page content references πŸ’…


✨ SYNOPSIS ✨

like, the incantations first. copy these EXACTLY, no cap:

#include <sys/param.h>
#include <vm/vm.h>
#include <vm/vm_page.h>

then the whole squad of functions:

int
vm_page_busied(vm_page_t m);

void
vm_page_busy_downgrade(vm_page_t m);

void
vm_page_busy_sleep(vm_page_t m, const char *msg);

int
vm_page_sbusied(vm_page_t m);

void
vm_page_sbusy(vm_page_t m);

int
vm_page_sleep_if_busy(vm_page_t m, const char *msg);

void
vm_page_sunbusy(vm_page_t m);

int
vm_page_trysbusy(vm_page_t m);

int
vm_page_tryxbusy(vm_page_t m);

int
vm_page_xbusied(vm_page_t m);

void
vm_page_xbusy(vm_page_t m);

void
vm_page_xunbusy(vm_page_t m);

and the three assertion girlies need these kernel options to even exist:

options INVARIANTS
options INVARIANT_SUPPORT

void
vm_page_assert_sbusied(vm_page_t m);

void
vm_page_assert_unbusied(vm_page_t m);

void
vm_page_assert_xbusied(vm_page_t m);

✨ DESCRIPTION ✨

okay so. Page identity is usually protected by higher level locks like vm_object locks and vm page locks. normally that's the vibe. πŸ™Œ

BUT β€” and this is the plot twist β€” sometimes it is not possible to hold such locks for the time necessary to complete the identity change. in that case, the page can be exclusively busied by a thread which needs to own the identity for a certain amount of time. main character thread energy only. πŸ‘‘

In other situations, threads do not need to change the identity of the page but they want to prevent other threads from changing the identity themselves. For example, when a thread wants to access or update page contents without a lock held, the page is shared busied.

🚨 THE RULE, bestie, do not skip this one: Before busying a page the vm_object lock must be held. The same rule applies when a page is unbusied. This makes the vm_object lock a real busy interlock.

now let's go function by function, no skipping, i love a complete list πŸŽ€

  • vm_page_busied() β€” returns non-zero if the current thread busied m in either exclusive or shared mode. Returns zero otherwise.
  • vm_page_busy_downgrade() β€” must be used to downgrade m from an exclusive busy state to a shared busy state.
  • vm_page_busy_sleep() β€” puts the invoking thread to sleep using the appropriate waitchannels for the busy mechanism. The parameter msg is a string describing the sleep condition for userland tools. 😴
  • vm_page_busied() β€” returns non-zero if the current thread busied m in shared mode. Returns zero otherwise.
  • vm_page_sbusy() β€” shared busies m.
  • vm_page_sleep_if_busy() β€” puts the invoking thread to sleep, using the appropriate waitchannels for the busy mechanism, if m. is busied in either exclusive or shared mode. If the invoking thread slept a non-zero value is returned, otherwise 0 is returned. The parameter msg is a string describing the sleep condition for userland tools.
  • vm_page_sunbusy() β€” shared unbusies m.
  • vm_page_trysbusy() β€” attempts to shared busy m. If the operation cannot immediately succeed vm_page_trysbusy() returns 0, otherwise a non-zero value is returned.
  • vm_page_tryxbusy() β€” attempts to exclusive busy m. If the operation cannot immediately succeed vm_page_tryxbusy() returns 0, otherwise a non-zero value is returned.
  • vm_page_xbusied() β€” returns non-zero if the current thread busied m in exclusive mode. Returns zero otherwise.
  • vm_page_xbusy() β€” exclusive busies m.
  • vm_page_xunbusy() β€” exclusive unbusies m. Assertions on the busy state allow kernels compiled with options INVARIANTS and options INVARIANT_SUPPORT to panic if they are not respected. πŸ’€

and now the assertion trio, the ones that will absolutely call you out:

  • vm_page_assert_sbusied() β€” panics if m is not shared busied.
  • vm_page_assert_unbusied() β€” panics if m is not unbusied.
  • vm_page_assert_xbusied() β€” panics if m is not exclusive busied.

🌈 SEE ALSO 🌈

go read these next, i promise they're worth it 🫢


and that's the page, bestie!! this one came out of Debian, dated August 07, 2013 β€” yeah it's a classic, it's been slaying in the Kernel Developer's Manual since forever, mwah πŸ’‹βœ¨ go busy a page responsibly, and remember: hold that vm_object lock. periodt. πŸ’–

πŸ“¦ where this page comes from