NetStack: Fix locking
Change the monitor_lock to be a recursive_lock, fixing #7039. Notify_device_monitor acquires the monitor lock, then the monitor unregisters itself, calling unregister_device_monitor, which acquires the monitor lock again.
This commit is contained in:
@@ -171,7 +171,7 @@ allocate_device_interface(net_device* device, net_device_module_info* module)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
recursive_lock_init(&interface->receive_lock, "device interface receive");
|
recursive_lock_init(&interface->receive_lock, "device interface receive");
|
||||||
mutex_init(&interface->monitor_lock, "device interface monitors");
|
recursive_lock_init(&interface->monitor_lock, "device interface monitors");
|
||||||
|
|
||||||
char name[128];
|
char name[128];
|
||||||
snprintf(name, sizeof(name), "%s receive queue", device->name);
|
snprintf(name, sizeof(name), "%s receive queue", device->name);
|
||||||
@@ -206,7 +206,7 @@ error2:
|
|||||||
uninit_fifo(&interface->receive_queue);
|
uninit_fifo(&interface->receive_queue);
|
||||||
error1:
|
error1:
|
||||||
recursive_lock_destroy(&interface->receive_lock);
|
recursive_lock_destroy(&interface->receive_lock);
|
||||||
mutex_destroy(&interface->monitor_lock);
|
recursive_lock_destroy(&interface->monitor_lock);
|
||||||
delete interface;
|
delete interface;
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -216,7 +216,7 @@ error1:
|
|||||||
static void
|
static void
|
||||||
notify_device_monitors(net_device_interface* interface, int32 event)
|
notify_device_monitors(net_device_interface* interface, int32 event)
|
||||||
{
|
{
|
||||||
MutexLocker locker(interface->monitor_lock);
|
RecursiveLocker locker(interface->monitor_lock);
|
||||||
|
|
||||||
DeviceMonitorList::Iterator iterator
|
DeviceMonitorList::Iterator iterator
|
||||||
= interface->monitor_funcs.GetIterator();
|
= interface->monitor_funcs.GetIterator();
|
||||||
@@ -392,7 +392,7 @@ put_device_interface(struct net_device_interface* interface)
|
|||||||
device->module->uninit_device(device);
|
device->module->uninit_device(device);
|
||||||
put_module(moduleName);
|
put_module(moduleName);
|
||||||
|
|
||||||
mutex_destroy(&interface->monitor_lock);
|
recursive_lock_destroy(&interface->monitor_lock);
|
||||||
recursive_lock_destroy(&interface->receive_lock);
|
recursive_lock_destroy(&interface->receive_lock);
|
||||||
delete interface;
|
delete interface;
|
||||||
}
|
}
|
||||||
@@ -478,7 +478,7 @@ void
|
|||||||
device_interface_monitor_receive(net_device_interface* interface,
|
device_interface_monitor_receive(net_device_interface* interface,
|
||||||
net_buffer* buffer)
|
net_buffer* buffer)
|
||||||
{
|
{
|
||||||
MutexLocker locker(interface->monitor_lock);
|
RecursiveLocker locker(interface->monitor_lock);
|
||||||
|
|
||||||
DeviceMonitorList::Iterator iterator
|
DeviceMonitorList::Iterator iterator
|
||||||
= interface->monitor_funcs.GetIterator();
|
= interface->monitor_funcs.GetIterator();
|
||||||
@@ -706,7 +706,7 @@ register_device_monitor(net_device* device, net_device_monitor* monitor)
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return B_DEVICE_NOT_FOUND;
|
return B_DEVICE_NOT_FOUND;
|
||||||
|
|
||||||
MutexLocker monitorLocker(interface->monitor_lock);
|
RecursiveLocker monitorLocker(interface->monitor_lock);
|
||||||
interface->monitor_funcs.Add(monitor);
|
interface->monitor_funcs.Add(monitor);
|
||||||
atomic_add(&interface->monitor_count, 1);
|
atomic_add(&interface->monitor_count, 1);
|
||||||
|
|
||||||
@@ -725,7 +725,7 @@ unregister_device_monitor(net_device* device, net_device_monitor* monitor)
|
|||||||
if (interface == NULL)
|
if (interface == NULL)
|
||||||
return B_DEVICE_NOT_FOUND;
|
return B_DEVICE_NOT_FOUND;
|
||||||
|
|
||||||
MutexLocker monitorLocker(interface->monitor_lock);
|
RecursiveLocker monitorLocker(interface->monitor_lock);
|
||||||
|
|
||||||
// search for the monitor
|
// search for the monitor
|
||||||
|
|
||||||
@@ -776,7 +776,7 @@ device_removed(net_device* device)
|
|||||||
|
|
||||||
// By now all of the monitors must have removed themselves. If they
|
// By now all of the monitors must have removed themselves. If they
|
||||||
// didn't, they'll probably wait forever to be callback'ed again.
|
// didn't, they'll probably wait forever to be callback'ed again.
|
||||||
mutex_lock(&interface->monitor_lock);
|
recursive_lock_lock(&interface->monitor_lock);
|
||||||
interface->monitor_funcs.RemoveAll();
|
interface->monitor_funcs.RemoveAll();
|
||||||
|
|
||||||
// All of the readers should be gone as well since we are out of
|
// All of the readers should be gone as well since we are out of
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
|
|||||||
int32 deframe_ref_count;
|
int32 deframe_ref_count;
|
||||||
|
|
||||||
int32 monitor_count;
|
int32 monitor_count;
|
||||||
mutex monitor_lock;
|
recursive_lock monitor_lock;
|
||||||
DeviceMonitorList monitor_funcs;
|
DeviceMonitorList monitor_funcs;
|
||||||
|
|
||||||
DeviceHandlerList receive_funcs;
|
DeviceHandlerList receive_funcs;
|
||||||
|
|||||||
Reference in New Issue
Block a user