Date: Thu, 14 Dec 2000 07:16:16 -0800 From: Julian Elischer <julian@elischer.org> To: smp@freebsd.org Subject: Mutex roadmap Message-ID: <3A38E440.B89DA298@elischer.org>
next in thread | raw e-mail | index | archive | help
In my attempts to understand locking on behaplf of netgraph, I ended up writing up this little roadmap of where things are... In the hope that SOMEONE finds it useful, I'm posting it here. ====== Start Roadmap ======= Basic roadmap to Mutex sources in FreeBSD. What is where, what it calls and where to find that.. ====================================================================== mutex structure: (mtx) defined in sys/mutex.h extended with an external structure (mtx_debug) when WITNESS defined. =========== BASIC calls used in the kernel by programmers =============== mtx_enter() is a MACRO that wraps _mtx_enter() with __LINE__ and __FILE__ info. defined in sys/mutex.h mtx_exit() is a MACRO that wraps _mtx_exit() with __LINE__ and __FILE__ info. defined in sys/mutex.h ============= Actual calls after cpp (Not used by programmer directly)==== _mutex_enter() An inline finction that is defined in sys/mutex.h Also compiled into an actual function in kern/mutex.c by including the inlines but removing the word "__inline" The inline version usually knows the constant values of the 'type' argument when expanded and can therefore optimise away all code branches that are not required. Usually this is almost all of the function. It uses the following primatives: disable_intr() _getlock_norecurse() _getlock_spin_block() _getlock_sleep() As well as possibly WITNESS_ENTER() if it is defined. _mutex_exit() An inline finction that is defined in sys/mutex.h Also compiled into an actual function in kern/mutex.c by including the inlines but removing the word "__inline" The inline version usually knows the constant values of the 'type' argument when expanded and can therefore optimise away all code branches that are not required. Usually this is almost all of the function. It uses the following primatives: _release_lock_quick enable_intr() restore_intr() _exitlock_spin() _exitlock() _exitlock_norecurse() As well as possibly WITNESS_EXIT() if it is defined. mtx_enter_hard() This is a real function, defined in kern/kern_mutex.c. it does all the hard work when a mutex has to stall or otherwise do some hard work. The _getlock (below) primatives call this when things get difficult and slow. calls: mtx_enter() mtx_exit() mtx_assert() _obtain_lock() atomic_set_ptr() atomic_cmpset_ptr() propagate_priority() mi_switch() mtx_exit_hard() This is a real function, defined in kern/kern_mutex.c. it does all the hard work when a mutex has to stall or otherwise do some hard work. The _getlock primatives call this when things get difficult and slow. calls: mtx_enter() mtx_exit() restore_intr() _release_lock_quick() atomic_store_rel_ptr() atomic_clear_ptr() setrunqueue() mi_switch() ================= Basic mutex building blocks ======================== These can have machine dependent versions that can over-ride the machine independent versions. The machine independent versions go on to use more primative operations. (see below) The implement basic parts of locking. _getlock_norecurse() Defined in sys/mutex.h if not defined already. calls _obtain_lock() and mtx_enter_hard() for i386 it has an overriding definition in i386/include/mutex.h (disabled) _getlock_spin_block() Defined in sys/mutex.h if not defined already. Calls save_intr(), disable_intr(), _obtain_lock() and mtx_enter_hard(). Has overriding definitions in alpha/include/mutex.h i386/include/mutex.h (disabled) _getlock_sleep() Defined in sys/mutex.h if not defined already. Calls _obtain_lock(), mtx_enter_hard() and atomic_set_ptr(). For i386 it has an overriding definition in i386/include/mutex.h (disabled) _exitlock_norecurse Defined in sys/mutex.h if not defined already. calls _release_lock() and mtx_exit_hard() for i386 it has an overriding definition in i386/include/mutex.h (disabled) _exitlock Defined in sys/mutex.h if not defined already. calls _release_lock(), atomic_clear_ptr() and mtx_exit_hard() for i386 it has an overriding definition in i386/include/mutex.h (disabled) _exitlock_spin Defined in sys/mutex.h if not defined already. calls _release_lock_quick() and restore_intr() for i386 it has an overriding definition in i386/include/mutex.h (disabled) ============== Macros that implement assembler locking primatives ==== I'm not sure where these are used (I couldn't find any users). Or if they are compatible with the other stuff... are they coming of going? MTX_ENTER() Macro for non recursive spinlocks. (appears unused) alpha/include/mutex.h ia64/include/mutex.h i386/include/mutex.h MTX_ENTER_WITH_RECURSION() macro for recursive locks (appears unused) i386/include/mutex.h MTX_EXIT() Macro for non recursive spinlocks. (appears unused) alpha/include/mutex.h ia64/include/mutex.h i386/include/mutex.h MTX_EXIT_WITH_RECURSION() (appears unused) i386/include/mutex.h ======== Primatives used by MI building blocks. Per processor type ==== disable_intr() | save_intr() | All four are asm inlines defined per_processor restore_intr() | in the following files. enable_intr() | i386/include/cpufunc.h alpha/include/cpufunc.h ia64/include/cpufunc.h ======== Primatives used by MI building blocks. Can be overridden ==== These use the defined "standard MI atomic ops" _obtain_lock() defined in sys/mutex.h but can be over-ridden. calls atomic_cmpset_acq_ptr() _release_lock_quick() defined in sys/mutex.h but can be over-ridden. calls atomic_store_rel_ptr() _release_lock() defined in sys/mutex.h but can be over-ridden. calls atomic_cmpset_rel_ptr() ========= Standard MI atomic ops. Defined per processor.============== atomic stuff defined in {ia64,alpha,i386}/include/atomic.h largely by macros tha produce inline asm functions. only i386 examples detailed here. Note that on the alpha "compare and set" is quite expensive as it takes about 10 instructions. maybe we should use a different primative.. ====================== Examples ====================================== atomic_cmpset_rel_ptr() Defined in i386/include/atomic.h to be the same as: atomic_cmpset_ptr() (below) atomic_cmpset_acq_ptr() Defined in i386/include/atomic.h to be the same as: atomic_cmpset_ptr() (below) atomic_cmpset_ptr() Defined in i386/include/atomic.h using atomic_cmpset_int atomic_load_rel_ptr() Defined in i386/include/atomic.h using atomic_load_acq_int() atomic_store_rel_ptr() Defined in i386/include/atomic.h using atomic_store_rel_int() atomic_clear_ptr() | produced by macros in i386/include/atomic.h atomic_set_ptr() | atomic_cmpset_int() | atomic_store_rel_int | atomic_load_acq_int | ==== EOF===== -- __--_|\ Julian Elischer / \ julian@elischer.org ( OZ ) World tour 2000 ---> X_.---._/ presently in: Budapest v To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-smp" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3A38E440.B89DA298>