network stack: Fixed double mutex lock.
* device_removed() no longer uses get_device_interface() to avoid the double locking. * Introduced net_device_interface::busy member to avoid locking in device_removed() for too long. * This should fix #7252.
This commit is contained in:
parent
ceff2b88ae
commit
f17488662a
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2017, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
|
@ -152,6 +152,7 @@ domain_receive_adapter(void* cookie, net_device* device, net_buffer* buffer)
|
|||
static net_device_interface*
|
||||
find_device_interface(const char* name)
|
||||
{
|
||||
ASSERT_LOCKED_MUTEX(&sLock);
|
||||
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||
|
||||
while (net_device_interface* interface = iterator.Next()) {
|
||||
|
@ -182,6 +183,7 @@ allocate_device_interface(net_device* device, net_device_module_info* module)
|
|||
interface->device = device;
|
||||
interface->up_count = 0;
|
||||
interface->ref_count = 1;
|
||||
interface->busy = false;
|
||||
interface->monitor_count = 0;
|
||||
interface->deframe_func = NULL;
|
||||
interface->deframe_ref_count = 0;
|
||||
|
@ -409,6 +411,9 @@ get_device_interface(uint32 index)
|
|||
DeviceInterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||
while (net_device_interface* interface = iterator.Next()) {
|
||||
if (interface->device->index == index) {
|
||||
if (interface->busy)
|
||||
break;
|
||||
|
||||
if (atomic_add(&interface->ref_count, 1) != 0)
|
||||
return interface;
|
||||
}
|
||||
|
@ -428,6 +433,9 @@ get_device_interface(const char* name, bool create)
|
|||
|
||||
net_device_interface* interface = find_device_interface(name);
|
||||
if (interface != NULL) {
|
||||
if (interface->busy)
|
||||
return NULL;
|
||||
|
||||
if (atomic_add(&interface->ref_count, 1) != 0)
|
||||
return interface;
|
||||
|
||||
|
@ -763,11 +771,17 @@ device_removed(net_device* device)
|
|||
{
|
||||
MutexLocker locker(sLock);
|
||||
|
||||
// hold a reference to the device interface being removed
|
||||
// so our put_() will (eventually) do the final cleanup
|
||||
net_device_interface* interface = get_device_interface(device->name, false);
|
||||
net_device_interface* interface = find_device_interface(device->name);
|
||||
if (interface == NULL)
|
||||
return B_DEVICE_NOT_FOUND;
|
||||
if (interface->busy)
|
||||
return B_BUSY;
|
||||
|
||||
// Acquire a reference to the device interface being removed
|
||||
// so our put_() will (eventually) do the final cleanup
|
||||
atomic_add(&interface->ref_count, 1);
|
||||
interface->busy = true;
|
||||
locker.Unlock();
|
||||
|
||||
// Propagate the loss of the device throughout the stack.
|
||||
|
||||
|
@ -776,8 +790,9 @@ device_removed(net_device* device)
|
|||
|
||||
// By now all of the monitors must have removed themselves. If they
|
||||
// didn't, they'll probably wait forever to be callback'ed again.
|
||||
recursive_lock_lock(&interface->monitor_lock);
|
||||
RecursiveLocker monitorLocker(interface->monitor_lock);
|
||||
interface->monitor_funcs.RemoveAll();
|
||||
monitorLocker.Unlock();
|
||||
|
||||
// All of the readers should be gone as well since we are out of
|
||||
// interfaces and put_domain_datalink_protocols() is called for
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
|
||||
* Copyright 2006-2017, Haiku, Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
|
@ -32,12 +32,13 @@ struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
|
|||
uint32 up_count;
|
||||
// a device can be brought up by more than one interface
|
||||
int32 ref_count;
|
||||
bool busy;
|
||||
|
||||
net_deframe_func deframe_func;
|
||||
int32 deframe_ref_count;
|
||||
|
||||
int32 monitor_count;
|
||||
recursive_lock monitor_lock;
|
||||
recursive_lock monitor_lock;
|
||||
DeviceMonitorList monitor_funcs;
|
||||
|
||||
DeviceHandlerList receive_funcs;
|
||||
|
|
Loading…
Reference in New Issue