From 86766d6aca79d51865285f5956a48bb62fc1f23e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 6 Aug 2009 08:24:23 +0000 Subject: [PATCH] * handle_driver_events() kept the sDriversListLock locked over the whole time. But since this is also locked from within the driver/directory watcher (with the node monitor lock held), and handle_driver_events() could cause node monitoring updates, the locking order could be reverted, causing a deadlock (I just ran into). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32152 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../kernel/device_manager/legacy_drivers.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/device_manager/legacy_drivers.cpp b/src/system/kernel/device_manager/legacy_drivers.cpp index 3ffd1f6cbd..c395b250be 100644 --- a/src/system/kernel/device_manager/legacy_drivers.cpp +++ b/src/system/kernel/device_manager/legacy_drivers.cpp @@ -196,6 +196,7 @@ static int32 sDriverEvents; static EntryList sDriversToAdd; static EntryList sDriversToRemove; static mutex sDriversListLock = MUTEX_INITIALIZER("driversList"); + // inner lock, protects the sDriversToAdd/sDriversToRemove lists only static DirectoryWatcher sDirectoryWatcher; static DirectoryNodeHash sDirectoryNodeHash; static recursive_lock sLock; @@ -641,14 +642,19 @@ handle_driver_events(void */*_fs*/, int /*iteration*/) // something happened, let's see what it was - RecursiveLocker locker(sLock); - MutexLocker _(sDriversListLock); + RecursiveLocker _(sLock); + + // Add new drivers while (true) { + MutexLocker listLocker(sDriversListLock); + path_entry* path = sDriversToAdd.RemoveHead(); if (path == NULL) break; + listLocker.Unlock(); + legacy_driver* driver = (legacy_driver*)hash_lookup(sDriverHash, get_leaf(path->path)); if (driver == NULL) @@ -657,11 +663,18 @@ handle_driver_events(void */*_fs*/, int /*iteration*/) driver->binary_updated = true; delete path; } + + // Mark removed drivers as updated + while (true) { + MutexLocker listLocker(sDriversListLock); + path_entry* path = sDriversToRemove.RemoveHead(); if (path == NULL) break; + listLocker.Unlock(); + legacy_driver* driver = (legacy_driver*)hash_lookup(sDriverHash, get_leaf(path->path)); if (driver != NULL && get_priority(path->path) >= driver->priority) @@ -669,6 +682,8 @@ handle_driver_events(void */*_fs*/, int /*iteration*/) delete path; } + // Reload updated drivers + hash_iterator iterator; hash_open(sDriverHash, &iterator); legacy_driver *driver;