git: kernel - Fix spin_lock_shared() race

Matthew Dillon dillon at crater.dragonflybsd.org
Tue Oct 15 12:26:02 PDT 2013


commit 79a7c522d4894f079dd0900cfdb6a545560982f7
Author: Matthew Dillon <dillon at apollo.backplane.com>
Date:   Tue Oct 15 12:13:49 2013 -0700

    kernel - Fix spin_lock_shared() race
    
    * Fix a serious bug in the shared spinlock code.  There are numerous races.
      The main problem is that the spin_lock_shared*() inlines set the
      SPINLOCK_SHARED bit based on a non-atomic test, assuming that the previous
      atomic operation guarded the test:
    
          atomic_add_int(&spin->counta, 1);
          if (spin->counta == 1)
    	    atomic_set_int(&spin->counta, SPINLOCK_SHARED);
    
      However, this can race an exclusive spin lock in another thread inbetween
      the conditional and the atomic_set_int().  The exclusive spinlock code
      would have seen contention, but then does this:
    
    	atomic_clear_int(&spin->counta, SPINLOCK_SHARED);
    	atomic_add_int(&spin->counta, SPINLOCK_EXCLWAIT - 1);
    	...
    
      The exclusive spinlock code then assumes that the shared spinlock code
      can no longer set SPINLOCK_SHARED.  However, if this occurs just after
      the shared spinlock code's if (spin->counta == 1) but before it atomically
      sets the SHARED bit, we wind up in a situation where the exclusive spinlock
      code completes its operation and leaves the SHARED bit set.
    
      In other words, the code which believes it has sucessfully obtained an
      exclusive spinlock actually winds up getting a shared spinlock.  Oops!
    
    * Fixed by guarding the shared lock conditional and atomic op and changing
      the way shared lock contention is handled.
    
    * Case was only reproducable on monster, probably due to massive shared
      spinlock use in the pmap code on 48 cpu cores all fork/exec'ing /bin/sh
      at the same time.

Summary of changes:
 sys/kern/kern_spinlock.c | 24 +++++++++++++++++-------
 sys/sys/spinlock2.h      |  9 +++------
 2 files changed, 20 insertions(+), 13 deletions(-)

http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/79a7c522d4894f079dd0900cfdb6a545560982f7


-- 
DragonFly BSD source repository



More information about the Commits mailing list