Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages


home | help
RMLOCK(9)	       FreeBSD Kernel Developer's Manual	     RMLOCK(9)

     rmlock, rm_init, rm_init_flags, rm_destroy, rm_rlock, rm_try_rlock,
     rm_wlock, rm_runlock, rm_wunlock, rm_wowned, rm_sleep, rm_assert,
     RM_SYSINIT, RM_SYSINIT_FLAGS -- kernel reader/writer lock optimized for
     read-mostly access	patterns

     #include <sys/param.h>
     #include <sys/lock.h>
     #include <sys/rmlock.h>

     rm_init(struct rmlock *rm,	const char *name);

     rm_init_flags(struct rmlock *rm, const char *name,	int opts);

     rm_destroy(struct rmlock *rm);

     rm_rlock(struct rmlock *rm, struct	rm_priotracker*	tracker);

     rm_try_rlock(struct rmlock	*rm, struct rm_priotracker* tracker);

     rm_wlock(struct rmlock *rm);

     rm_runlock(struct rmlock *rm, struct rm_priotracker* tracker);

     rm_wunlock(struct rmlock *rm);

     rm_wowned(const struct rmlock *rm);

     rm_sleep(void *wchan, struct rmlock *rm, int priority, const char *wmesg,
	 int timo);

     options INVARIANTS

     rm_assert(struct rmlock *rm, int what);

     #include <sys/kernel.h>

     RM_SYSINIT(name, struct rmlock *rm, const char *desc);

     RM_SYSINIT_FLAGS(name, struct rmlock *rm, const char *desc, int flags);

     Read-mostly locks allow shared access to protected	data by	multiple
     threads, or exclusive access by a single thread.  The threads with	shared
     access are	known as readers since they only read the protected data.  A
     thread with exclusive access is known as a	writer since it	can modify
     protected data.

     Read-mostly locks are designed to be efficient for	locks almost exclu-
     sively used as reader locks and as	such should be used for	protecting
     data that rarely changes.	Acquiring an exclusive lock after the lock has
     been locked for shared access is an expensive operation.

     Normal read-mostly	locks are similar to rwlock(9) locks and follow	the
     same lock ordering	rules as rwlock(9) locks.  Read-mostly locks have full
     priority propagation like mutexes.	 Unlike	rwlock(9), read-mostly locks
     propagate priority	to both	readers	and writers.  This is implemented via
     the rm_priotracker	structure argument supplied to rm_rlock() and
     rm_runlock().  Readers can	recurse	if the lock is initialized with	the
     RM_RECURSE	option;	however, writers are never allowed to recurse.

     Sleepable read-mostly locks are created by	passing	RM_SLEEPABLE to
     rm_init_flags().  Unlike normal read-mostly locks,	sleepable read-mostly
     locks follow the same lock	ordering rules as sx(9)	locks.	Sleepable
     read-mostly locks do not propagate	priority to writers, but they do prop-
     agate priority to readers.	 Writers are permitted to sleep	while holding
     a read-mostly lock, but readers are not.  Unlike other sleepable locks
     such as sx(9) locks, readers must use try operations on other sleepable
     locks to avoid sleeping.

   Macros and Functions
     rm_init(struct rmlock *rm,	const char *name)
	     Initialize	the read-mostly	lock rm.  The name description is used
	     solely for	debugging purposes.  This function must	be called be-
	     fore any other operations on the lock.

     rm_init_flags(struct rmlock *rm, const char *name,	int opts)
	     Similar to	rm_init(), initialize the read-mostly lock rm with a
	     set of optional flags.  The opts arguments	contains one or	more
	     of	the following flags:

	     RM_NOWITNESS  Instruct witness(4) to ignore this lock.

	     RM_RECURSE	   Allow threads to recursively	acquire	shared locks
			   for rm.

	     RM_SLEEPABLE  Create a sleepable read-mostly lock.

	     RM_NEW	   If the kernel has been compiled with	option
			   INVARIANTS, rm_init_flags() will assert that	the rm
			   has not been	initialized multiple times without in-
			   tervening calls to rm_destroy() unless this option
			   is specified.

     rm_rlock(struct rmlock *rm, struct	rm_priotracker*	tracker)
	     Lock rm as	a reader using tracker to track	read owners of a lock
	     for priority propagation.	This data structure is only used in-
	     ternally by rmlock	and must persist until rm_runlock() has	been
	     called.  This data	structure can be allocated on the stack	since
	     readers cannot sleep.  If any thread holds	this lock exclusively,
	     the current thread	blocks,	and its	priority is propagated to the
	     exclusive holder.	If the lock was	initialized with the
	     RM_RECURSE	option the rm_rlock() function can be called when the
	     current thread has	already	acquired reader	access on rm.

     rm_try_rlock(struct rmlock	*rm, struct rm_priotracker* tracker)
	     Try to lock rm as a reader.  rm_try_rlock() will return 0 if the
	     lock cannot be acquired immediately; otherwise, the lock will be
	     acquired and a non-zero value will	be returned.  Note that
	     rm_try_rlock() may	fail even while	the lock is not	currently held
	     by	a writer.  If the lock was initialized with the	RM_RECURSE op-
	     tion, rm_try_rlock() will succeed if the current thread has al-
	     ready acquired reader access.

     rm_wlock(struct rmlock *rm)
	     Lock rm as	a writer.  If there are	any shared owners of the lock,
	     the current thread	blocks.	 The rm_wlock()	function cannot	be
	     called recursively.

     rm_runlock(struct rmlock *rm, struct rm_priotracker* tracker)
	     This function releases a shared lock previously acquired by
	     rm_rlock().  The tracker argument must match the tracker argument
	     used for acquiring	the shared lock

     rm_wunlock(struct rmlock *rm)
	     This function releases an exclusive lock previously acquired by

     rm_destroy(struct rmlock *rm)
	     This functions destroys a lock previously initialized with
	     rm_init().	 The rm	lock must be unlocked.

     rm_wowned(const struct rmlock *rm)
	     This function returns a non-zero value if the current thread owns
	     an	exclusive lock on rm.

     rm_sleep(void *wchan, struct rmlock *rm, int priority, const char *wmesg,
	     int timo)
	     This function atomically releases rm while	waiting	for an event.
	     The rm lock must be exclusively locked.  For more details on the
	     parameters	to this	function, see sleep(9).

     rm_assert(struct rmlock *rm, int what)
	     This function asserts that	the rm lock is in the state specified
	     by	what.  If the assertions are not true and the kernel is	com-
	     piled with	options	INVARIANTS and options INVARIANT_SUPPORT, the
	     kernel will panic.	 Currently the following base assertions are

	     RA_LOCKED	  Assert that current thread holds either a shared or
			  exclusive lock of rm.

	     RA_RLOCKED	  Assert that current thread holds a shared lock of

	     RA_WLOCKED	  Assert that current thread holds an exclusive	lock
			  of rm.

	     RA_UNLOCKED  Assert that current thread holds neither a shared
			  nor exclusive	lock of	rm.

	     In	addition, one of the following optional	flags may be specified

	     RA_RECURSED     Assert that the current thread holds a recursive
			     lock of rm.

	     RA_NOTRECURSED  Assert that the current thread does not hold a
			     recursive lock of rm.

     locking(9), mutex(9), panic(9), rwlock(9),	sema(9), sleep(9), sx(9)

     These functions appeared in FreeBSD 7.0.

     The rmlock	facility was written by	Stephan	Uphoff.	 This manual page was
     written by	Gleb Smirnoff for rwlock and modified to reflect rmlock	by
     Stephan Uphoff.

     The rmlock	implementation is currently not	optimized for single processor

     rm_try_rlock() can	fail transiently even when there is no writer, while
     another reader updates the	state on the local CPU.

     The rmlock	implementation uses a single per CPU list shared by all	rm-
     locks in the system.  If rmlocks become popular, hashing to multiple per
     CPU queues	may be needed to speed up the writer lock process.

FreeBSD	13.0		       November	11, 2017		  FreeBSD 13.0


Want to link to this manual page? Use this URL:

home | help