Skip site navigation (1)Skip section navigation (2)
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>