mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-20 11:11:24 +00:00
Check the lock lists to see if they are empty directly rather than
assigning a pointer to the list and then dereferencing the pointer as a second step. When the first spin lock is acquired, curthread is not in a critical section so it may be preempted and would end up using another CPUs lock list instead of its own. When this code was in witness_lock() this sequence was safe as curthread was in a critical section already since witness_lock() is called after the lock is acquired. Tested by: Daniel Lang dl at leo.org
This commit is contained in:
parent
6421d1dbcb
commit
776b99ee1a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=131884
@ -690,22 +690,34 @@ witness_checkorder(struct lock_object *lock, int flags, const char *file,
|
||||
if (class->lc_flags & LC_SLEEPLOCK) {
|
||||
/*
|
||||
* Since spin locks include a critical section, this check
|
||||
* impliclty enforces a lock order of all sleep locks before
|
||||
* implicitly enforces a lock order of all sleep locks before
|
||||
* all spin locks.
|
||||
*/
|
||||
if (td->td_critnest != 0)
|
||||
panic("blockable sleep lock (%s) %s @ %s:%d",
|
||||
class->lc_name, lock->lo_name, file, line);
|
||||
lock_list = &td->td_sleeplocks;
|
||||
} else
|
||||
lock_list = PCPU_PTR(spinlocks);
|
||||
|
||||
/*
|
||||
* Is this the first lock acquired? If so, then no order checking
|
||||
* is needed.
|
||||
*/
|
||||
if (*lock_list == NULL)
|
||||
return;
|
||||
/*
|
||||
* If this is the first lock acquired then just return as
|
||||
* no order checking is needed.
|
||||
*/
|
||||
if (td->td_sleeplocks == NULL)
|
||||
return;
|
||||
lock_list = &td->td_sleeplocks;
|
||||
} else {
|
||||
/*
|
||||
* If this is the first lock, just return as no order
|
||||
* checking is needed. We check this in both if clauses
|
||||
* here as unifying the check would require us to use a
|
||||
* critical section to ensure we don't migrate while doing
|
||||
* the check. Note that if this is not the first lock, we
|
||||
* are already in a critical section and are safe for the
|
||||
* rest of the check.
|
||||
*/
|
||||
if (PCPU_GET(spinlocks) == NULL)
|
||||
return;
|
||||
lock_list = PCPU_PTR(spinlocks);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check to see if we are recursing on a lock we already own. If
|
||||
|
Loading…
Reference in New Issue
Block a user