Improve patch in ticket #9377
Instead of locking the interface lock, set it busy and then unlock the interface list lock.
This commit is contained in:
@@ -445,6 +445,8 @@ InterfaceAddress::_Init(net_interface* netInterface, net_domain* netDomain)
|
|||||||
|
|
||||||
Interface::Interface(const char* interfaceName,
|
Interface::Interface(const char* interfaceName,
|
||||||
net_device_interface* deviceInterface)
|
net_device_interface* deviceInterface)
|
||||||
|
:
|
||||||
|
fBusy(false)
|
||||||
{
|
{
|
||||||
TRACE("Interface %p: new \"%s\", device interface %p\n", this,
|
TRACE("Interface %p: new \"%s\", device interface %p\n", this,
|
||||||
interfaceName, deviceInterface);
|
interfaceName, deviceInterface);
|
||||||
@@ -933,13 +935,13 @@ Interface::SetDown()
|
|||||||
if ((flags & IFF_UP) == 0)
|
if ((flags & IFF_UP) == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// TODO: We acquire also the net_interfaces lock here
|
RecursiveLocker interfacesLock(sLock);
|
||||||
// to avoid a lock inversion in the ipv6 protocol implementation
|
|
||||||
// (see ticket #9377).
|
if (IsBusy())
|
||||||
// A better solution would be to avoid locking the interface lock (fLock)
|
return;
|
||||||
// when calling the lower layers.
|
|
||||||
RecursiveLocker interfacesLocker(sLock);
|
SetBusy(true);
|
||||||
RecursiveLocker locker(fLock);
|
interfacesLock.Unlock();
|
||||||
|
|
||||||
DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
|
DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
|
||||||
while (domain_datalink* datalink = iterator.Next()) {
|
while (domain_datalink* datalink = iterator.Next()) {
|
||||||
@@ -947,6 +949,8 @@ Interface::SetDown()
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags &= ~IFF_UP;
|
flags &= ~IFF_UP;
|
||||||
|
|
||||||
|
SetBusy(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1076,10 +1080,11 @@ Interface::_SetUp()
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
|
RecursiveLocker interfacesLocker(sLock);
|
||||||
|
SetBusy(true);
|
||||||
|
interfacesLocker.Unlock();
|
||||||
|
|
||||||
// Propagate flag to all datalink protocols
|
// Propagate flag to all datalink protocols
|
||||||
|
|
||||||
RecursiveLocker locker(fLock);
|
|
||||||
|
|
||||||
DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
|
DatalinkTable::Iterator iterator = fDatalinkTable.GetIterator();
|
||||||
while (domain_datalink* datalink = iterator.Next()) {
|
while (domain_datalink* datalink = iterator.Next()) {
|
||||||
status = datalink->first_info->interface_up(datalink->first_protocol);
|
status = datalink->first_info->interface_up(datalink->first_protocol);
|
||||||
@@ -1097,6 +1102,7 @@ Interface::_SetUp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
down_device_interface(fDeviceInterface);
|
down_device_interface(fDeviceInterface);
|
||||||
|
SetBusy(false);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1109,6 +1115,8 @@ Interface::_SetUp()
|
|||||||
}
|
}
|
||||||
|
|
||||||
flags |= IFF_UP;
|
flags |= IFF_UP;
|
||||||
|
SetBusy(false);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1409,7 +1417,7 @@ get_interface(net_domain* domain, uint32 index)
|
|||||||
interface = sInterfaces.First();
|
interface = sInterfaces.First();
|
||||||
else
|
else
|
||||||
interface = find_interface(index);
|
interface = find_interface(index);
|
||||||
if (interface == NULL)
|
if (interface == NULL || interface->IsBusy())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
||||||
@@ -1426,7 +1434,7 @@ get_interface(net_domain* domain, const char* name)
|
|||||||
RecursiveLocker locker(sLock);
|
RecursiveLocker locker(sLock);
|
||||||
|
|
||||||
Interface* interface = find_interface(name);
|
Interface* interface = find_interface(name);
|
||||||
if (interface == NULL)
|
if (interface == NULL || interface->IsBusy())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
||||||
@@ -1445,6 +1453,8 @@ get_interface_for_device(net_domain* domain, uint32 index)
|
|||||||
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||||
while (Interface* interface = iterator.Next()) {
|
while (Interface* interface = iterator.Next()) {
|
||||||
if (interface->device->index == index) {
|
if (interface->device->index == index) {
|
||||||
|
if (interface->IsBusy())
|
||||||
|
return NULL;
|
||||||
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -1470,6 +1480,8 @@ get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
|
|||||||
|
|
||||||
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||||
while (Interface* interface = iterator.Next()) {
|
while (Interface* interface = iterator.Next()) {
|
||||||
|
if (interface->IsBusy())
|
||||||
|
continue;
|
||||||
// Test if the hardware address matches, or if the given interface
|
// Test if the hardware address matches, or if the given interface
|
||||||
// matches, or if at least the index matches.
|
// matches, or if at least the index matches.
|
||||||
if ((linkAddress.sdl_alen == interface->device->address.length
|
if ((linkAddress.sdl_alen == interface->device->address.length
|
||||||
@@ -1479,6 +1491,8 @@ get_interface_for_link(net_domain* domain, const sockaddr* _linkAddress)
|
|||||||
&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
|
&& !strcmp(interface->name, (const char*)linkAddress.sdl_data))
|
||||||
|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
|
|| (linkAddress.sdl_nlen == 0 && linkAddress.sdl_alen == 0
|
||||||
&& linkAddress.sdl_index == interface->index)) {
|
&& linkAddress.sdl_index == interface->index)) {
|
||||||
|
if (interface->IsBusy())
|
||||||
|
return NULL;
|
||||||
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
if (interface->CreateDomainDatalinkIfNeeded(domain) != B_OK)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@@ -1516,6 +1530,9 @@ get_interface_address_for_destination(net_domain* domain,
|
|||||||
|
|
||||||
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||||
while (Interface* interface = iterator.Next()) {
|
while (Interface* interface = iterator.Next()) {
|
||||||
|
if (interface->IsBusy())
|
||||||
|
continue;
|
||||||
|
|
||||||
InterfaceAddress* address
|
InterfaceAddress* address
|
||||||
= interface->AddressForDestination(domain, destination);
|
= interface->AddressForDestination(domain, destination);
|
||||||
if (address != NULL)
|
if (address != NULL)
|
||||||
@@ -1543,6 +1560,8 @@ get_interface_address_for_link(net_domain* domain, const sockaddr* address,
|
|||||||
|
|
||||||
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
InterfaceList::Iterator iterator = sInterfaces.GetIterator();
|
||||||
while (Interface* interface = iterator.Next()) {
|
while (Interface* interface = iterator.Next()) {
|
||||||
|
if (interface->IsBusy())
|
||||||
|
continue;
|
||||||
// Test if the hardware address matches, or if the given interface
|
// Test if the hardware address matches, or if the given interface
|
||||||
// matches, or if at least the index matches.
|
// matches, or if at least the index matches.
|
||||||
if (linkAddress.sdl_alen == interface->device->address.length
|
if (linkAddress.sdl_alen == interface->device->address.length
|
||||||
|
|||||||
@@ -152,6 +152,9 @@ public:
|
|||||||
domain_datalink* DomainDatalink(net_domain* domain)
|
domain_datalink* DomainDatalink(net_domain* domain)
|
||||||
{ return DomainDatalink(domain->family); }
|
{ return DomainDatalink(domain->family); }
|
||||||
|
|
||||||
|
inline void SetBusy(bool busy) { atomic_set(&fBusy, busy ? 1 : 0); };
|
||||||
|
inline bool IsBusy() const { return atomic_get((int32*)&fBusy) == 1 ;};
|
||||||
|
|
||||||
#if ENABLE_DEBUGGER_COMMANDS
|
#if ENABLE_DEBUGGER_COMMANDS
|
||||||
void Dump() const;
|
void Dump() const;
|
||||||
#endif
|
#endif
|
||||||
@@ -166,6 +169,7 @@ private:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
recursive_lock fLock;
|
recursive_lock fLock;
|
||||||
|
int32 fBusy;
|
||||||
net_device_interface* fDeviceInterface;
|
net_device_interface* fDeviceInterface;
|
||||||
AddressList fAddresses;
|
AddressList fAddresses;
|
||||||
DatalinkTable fDatalinkTable;
|
DatalinkTable fDatalinkTable;
|
||||||
|
|||||||
Reference in New Issue
Block a user