Skip to content
  • Andriy Gapon's avatar
    safer wait-free iteration of shared interrupt handlers · e0fa977e
    Andriy Gapon authored
    The code that iterates a list of interrupt handlers for a (shared)
    interrupt, whether in the ISR context or in the context of an interrupt
    thread, does so in a lock-free fashion.   Thus, the routines that modify
    the list need to take special steps to ensure that the iterating code
    has a consistent view of the list.  Previously, those routines tried to
    play nice only with the code running in the ithread context.  The
    iteration in the ISR context was left to a chance.
    
    After commit r336635 atomic operations and memory fences are used to
    ensure that ie_handlers list is always safe to navigate with respect to
    inserting and removal of list elements.
    
    There is still a question of when it is safe to actually free a removed
    element.
    
    The idea of this change is somewhat similar to the idea of the epoch
    based reclamation.  There are some simplifications comparing to the
    general epoch based reclamation.  All writers are serialized using a
    mutex, so we do not need to worry about concurrent modifications.  Also,
    all read accesses from the open context are serialized too.
    
    So, we can get away just two epochs / phases.  When a thread removes an
    element it switches the global phase from the current phase to the other
    and then drains the previous phase.  Only after the draining the removed
    element gets actually freed. The code that iterates the list in the ISR
    context takes a snapshot of the global phase and then increments the use
    count of that phase before iterating the list.  The use count (in the
    same phase) is decremented after the iteration.  This should ensure that
    there should be no iteration over the removed element when its gets
    freed.
    
    This commit also simplifies the coordination with the interrupt thread
    context.  Now we always schedule the interrupt thread when removing one
    of handlers for its interrupt.  This makes the code both simpler and
    safer as the interrupt thread masks the interrupt thus ensuring that
    there is no interaction with the ISR context.
    
    P.S.  This change matters only for shared interrupts and I realize that
    those are becoming a thing of the past (and quickly).  I also understand
    that the problem that I am trying to solve is extremely rare.
    
    PR:		229106
    Reviewed by:	cem
    Discussed with:	Samy Al Bahra
    MFC after:	5 weeks
    Differential Revision: https://reviews.freebsd.org/D15905
    e0fa977e