whenever an interface is deleted, call put_domain_datalink_protocols() so all readers are unregistered.

- Unfortunely this requires RX lock to become a recursive lock.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20621 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Hugo Santos 2007-04-08 22:00:52 +00:00
parent eaf517212a
commit 6473469039
4 changed files with 24 additions and 15 deletions

View File

@ -45,7 +45,7 @@ device_reader_thread(void *_interface)
net_device *device = interface->device;
status_t status = B_OK;
BenaphoreLocker rx_lock(interface->rx_lock);
RecursiveLocker rx_lock(interface->rx_lock);
while (device->flags & IFF_UP) {
net_buffer *buffer;

View File

@ -213,7 +213,7 @@ domain_interface_control(net_domain_private *domain, int32 option,
// and domain locks are required, we MUST obtain the RX
// lock before the domain lock. This order MUST NOT ever
// be reversed under the penalty of deadlock.
BenaphoreLocker _1(device->rx_lock);
RecursiveLocker _1(device->rx_lock);
BenaphoreLocker _2(domain->lock);
net_interface *interface = find_interface(domain, name);

View File

@ -190,6 +190,12 @@ delete_interface(net_interface_private *interface)
// down_device_interface() -- if upcount reaches 0
interface_set_down(interface);
// This call requires the RX Lock to be a recursive
// lock since each uninit_protocol() call may call
// again into the stack to unregister a reader for
// instance, which tries to obtain the RX lock again.
put_domain_datalink_protocols(interface);
put_device_interface(interface->device_interface);
free(interface->address);
@ -325,7 +331,7 @@ put_device_interface(struct net_device_interface *interface)
interface->module->uninit_device(interface->device);
put_module(interface->module->info.name);
benaphore_destroy(&interface->rx_lock);
recursive_lock_destroy(&interface->rx_lock);
delete interface;
}
@ -392,7 +398,8 @@ get_device_interface(const char *name, bool create)
// create new module interface for this
interface = new (std::nothrow) net_device_interface;
if (interface != NULL) {
if (benaphore_init(&interface->rx_lock, "rx lock") >= B_OK) {
if (recursive_lock_init(&interface->rx_lock,
"rx lock") >= B_OK) {
interface->name = device->name;
interface->module = module;
interface->device = device;
@ -446,13 +453,13 @@ down_device_interface(net_device_interface *interface)
// one of the callers must hold a reference to the net_device_interface
// usually it is one of the net_interfaces.
benaphore_unlock(&interface->rx_lock);
recursive_lock_unlock(&interface->rx_lock);
// make sure the reader thread is gone before shutting down the interface
status_t status;
wait_for_thread(reader_thread, &status);
benaphore_lock(&interface->rx_lock);
recursive_lock_lock(&interface->rx_lock);
}
@ -473,7 +480,7 @@ unregister_device_deframer(net_device *device)
if (interface == NULL)
return ENODEV;
BenaphoreLocker _(interface->rx_lock);
RecursiveLocker _(interface->rx_lock);
if (--interface->deframe_ref_count == 0)
interface->deframe_func = NULL;
@ -502,7 +509,7 @@ register_device_deframer(net_device *device, net_deframe_func deframeFunc)
if (interface == NULL)
return ENODEV;
BenaphoreLocker _(interface->rx_lock);
RecursiveLocker _(interface->rx_lock);
if (interface->deframe_func != NULL && interface->deframe_func != deframeFunc)
return B_ERROR;
@ -536,7 +543,7 @@ register_device_handler(struct net_device *device, int32 type,
if (interface == NULL)
return ENODEV;
BenaphoreLocker _(interface->rx_lock);
RecursiveLocker _(interface->rx_lock);
// see if such a handler already for this device
@ -572,7 +579,7 @@ unregister_device_handler(struct net_device *device, int32 type)
if (interface == NULL)
return ENODEV;
BenaphoreLocker _(interface->rx_lock);
RecursiveLocker _(interface->rx_lock);
// search for the handler
@ -605,7 +612,7 @@ register_device_monitor(net_device *device, net_device_monitor *monitor)
if (interface == NULL)
return ENODEV;
BenaphoreLocker _(interface->rx_lock);
RecursiveLocker _(interface->rx_lock);
interface->monitor_funcs.Add(monitor);
return B_OK;
}
@ -621,7 +628,7 @@ unregister_device_monitor(net_device *device, net_device_monitor *monitor)
if (interface == NULL)
return ENODEV;
BenaphoreLocker _(interface->rx_lock);
RecursiveLocker _(interface->rx_lock);
// search for the monitor
@ -669,7 +676,7 @@ device_removed(net_device *device)
// This is very complex, refer to delete_interface() for
// further details.
BenaphoreLocker _(interface->rx_lock);
RecursiveLocker _(interface->rx_lock);
// this will possibly call:
// remove_interface_from_domain() [domain gets locked]
@ -690,7 +697,9 @@ device_removed(net_device *device)
// didn't, they'll probably wait forever to be callback'ed again.
interface->monitor_funcs.RemoveAll();
// TODO: make sure all readers are gone
// All of the readers should be gone as well since we are out of
// interfaces and `put_domain_datalink_protocols' is called for
// each delete_interface().
put_device_interface(interface);

View File

@ -42,7 +42,7 @@ struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
DeviceMonitorList monitor_funcs;
DeviceHandlerList receive_funcs;
benaphore rx_lock;
recursive_lock rx_lock;
};
typedef DoublyLinkedList<net_device_interface> DeviceInterfaceList;