  The lock is a building-block synchronization primitive that enables mutually
exclusive access to shared data in shared-memory parallel programs. Mutual
exclusion is typically achieved by guarding the code that accesses the shared
data with a pair of lock() and unlock() operations. Concurrency bugs arise when
this ordering of operations is violated. In this paper, we study a particular
pattern of misuse where an unlock() is issued without first issuing a lock(),
which can happen in code with complex control flow. This misuse is surprisingly
common in several important open-source repositories we study. We
systematically study what happens due to this misuse in several popular locking
algorithms. We study how misuse can be detected and how the locking protocols
can be fixed to avoid the unwanted consequences of misuse. Most locks require
simple changes to detect and prevent this misuse. We evaluate the performance
traits of modified implementations, which show mild performance penalties in
most scalable locks.
