USB: Release the device manager lock before exploring.

Exploring can take a while, and if we hold the device manager
lock the whole time, we'll block a lot of other things on the
system (including open() calls to anything in devfs.)

So, instead of holding the lock continuously, we now lock it
only temporarily, and instead add protection against deadlocks
when called by other threads besides the explore thread.
This commit is contained in:
Augustin Cavalier
2024-07-15 14:09:15 -04:00
parent 12bfa3571c
commit c003525101
2 changed files with 22 additions and 6 deletions
+21 -5
View File
@@ -217,11 +217,26 @@ Stack::ExploreThread(void *data)
void
Stack::Explore()
{
// Acquire the device manager lock before the explore lock, to prevent lock-order inversion.
RecursiveLocker dmLocker(device_manager_get_lock());
recursive_lock* dmLock = device_manager_get_lock();
if (find_thread(NULL) != fExploreThread
&& RECURSIVE_LOCK_HOLDER(dmLock) == find_thread(NULL)) {
// This should only happen during the initial device scan, during which
// we should be able to acquire the explore lock immediately (since the
// explore thread will be waiting on the device manager lock as below),
// but in case we aren't, use a timeout to avoid lock-order-inversion deadlocks.
if (mutex_lock_with_timeout(&fExploreLock, B_RELATIVE_TIMEOUT, 1000) != B_OK) {
release_sem(fExploreSem);
return;
}
} else {
// Temporarily acquire the device manager lock, to ensure it isn't scanning.
RecursiveLocker dmLocker(dmLock);
if (mutex_lock(&fExploreLock) != B_OK)
return;
if (mutex_lock(&fExploreLock) != B_OK)
return;
dmLocker.Unlock();
}
int32 semCount = 0;
get_sem_count(fExploreSem, &semCount);
@@ -256,12 +271,13 @@ Stack::Explore()
void
Stack::AddBusManager(BusManager *busManager)
{
MutexLocker _(fExploreLock);
fBusManagers.PushBack(busManager);
}
int32
Stack::IndexOfBusManager(BusManager *busManager)
Stack::IndexOfBusManager(BusManager *busManager) const
{
return fBusManagers.IndexOf(busManager);
}
@@ -143,7 +143,7 @@ public:
Object * GetObjectNoLock(usb_id id) const;
void AddBusManager(BusManager *bus);
int32 IndexOfBusManager(BusManager *bus);
int32 IndexOfBusManager(BusManager *bus) const;
BusManager * BusManagerAt(int32 index) const;
status_t AllocateChunk(void **logicalAddress,