• Ingo Molnar's avatar
    [PATCH] lockdep core: improve the lock-chain-hash · 03cbc358
    Ingo Molnar authored
    With CONFIG_DEBUG_LOCK_ALLOC turned off i was getting sporadic failures in
    the locking self-test:
    
      ------------>
      | Locking API testsuite:
      ----------------------------------------------------------------------------
                                       | spin |wlock |rlock |mutex | wsem | rsem |
        --------------------------------------------------------------------------
                           A-A deadlock:  ok  |  ok  |  ok  |  ok  |  ok  |  ok  |
                       A-B-B-A deadlock:  ok  |  ok  |  ok  |  ok  |  ok  |  ok  |
                   A-B-B-C-C-A deadlock:  ok  |  ok  |  ok  |  ok  |  ok  |  ok  |
                   A-B-C-A-B-C deadlock:  ok  |  ok  |  ok  |  ok  |  ok  |  ok  |
               A-B-B-C-C-D-D-A deadlock:  ok  |FAILED|  ok  |  ok  |  ok  |  ok  |
               A-B-C-D-B-D-D-A deadlock:  ok  |  ok  |  ok  |  ok  |  ok  |  ok  |
               A-B-C-D-B-C-D-A deadlock:  ok  |  ok  |  ok  |  ok  |  ok  |FAILED|
    
    after much debugging it turned out to be caused by accidental chain-hash
    key collisions.  The current hash is:
    
     #define iterate_chain_key(key1, key2) \
    	(((key1) << MAX_LOCKDEP_KEYS_BITS/2) ^ \
    	((key1) >> (64-MAX_LOCKDEP_KEYS_BITS/2)) ^ \
     	(key2))
    
    where MAX_LOCKDEP_KEYS_BITS is 11.  This hash is pretty good as it will
    shift by 5 bits in every iteration, where every new ID 'mixed' into the
    hash would have up to 11 bits.  But because there was a 6 bits overlap
    between subsequent IDs and their high bits tended to be similar, there was
    a chance for accidental chain-hash collision for a low number of locks
    held.
    
    the solution is to shift by 11 bits:
    
     #define iterate_chain_key(key1, key2) \
    	(((key1) << MAX_LOCKDEP_KEYS_BITS) ^ \
    	((key1) >> (64-MAX_LOCKDEP_KEYS_BITS)) ^ \
     	(key2))
    
    This keeps the hash perfect up to 5 locks held, but even above that the
    hash is still good because 11 bits is a relative prime to the total 64
    bits, so a complete match will only occur after 64 held locks (which doesnt
    happen in Linux).  Even after 5 locks held, entropy of the 5 IDs mixed into
    the hash is already good enough so that overlap doesnt generate a colliding
    hash ID.
    
    with this change the false positives went away.
    Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
    Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    03cbc358
lockdep.c 68 KB