commit 8319957b9f679319761213e5c0e28293afd26e34 Author: Matthew Dillon <dil...@apollo.backplane.com> Date: Wed Feb 14 11:49:40 2018 -0800
kernel - Fix rare missed wakeup() in lockmgr * Fix a rare missed wakeup() case in lockmgr. lk_count can briefly become (SHARED | 0 counts | (EXREQ or UPREQ)). Three competing cores can then cause a situation where undo_shreq() fails to issue a wakeup() to threads acquiring a shared lock that are blocked waiting for the EXREQ or UPREQ Issue the missing wakeup() for this case. * This race arises because of an optimization we make when dropping a shared lock. atomic_fcmpset*() loops are fairly poor at dealing with concurrent increments and decrements, so undo_shreq() (which is also used when releasing a standard shared lock) decrements the shared lock count first, then deals with EXREQ or UPREQ afterwords. Usually a shared lock request bumps the shared lock count before blocking, which other lock releases use to determine the need for a wakeup(). However, shared lock requests cannot bump the shared lock count when the lock is already held SHARED but there is an EXREQ or UPREQ pending, because doing do basically grants the shared lock immediately. This combination leads to the brief situation which allows other cpu cores to squeeze in operations of their own without realizing that someone might be blocked trying to obtain a shared lock, but with no shared count present to indicate so. If the undo_shreq()'s later atomic_fcmpset*() calls then fail, or find that there is no EXREQ or UPREQ pending, it fails to issue the needed wakeup(). Summary of changes: sys/kern/kern_lock.c | 10 ++++++++++ 1 file changed, 10 insertions(+) http://gitweb.dragonflybsd.org/dragonfly.git/commitdiff/8319957b9f679319761213e5c0e28293afd26e34 -- DragonFly BSD source repository