diff --git a/src/add-ons/kernel/network/stack/datalink.cpp b/src/add-ons/kernel/network/stack/datalink.cpp index a42d964d46..aed13c4d8b 100644 --- a/src/add-ons/kernel/network/stack/datalink.cpp +++ b/src/add-ons/kernel/network/stack/datalink.cpp @@ -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; diff --git a/src/add-ons/kernel/network/stack/domains.cpp b/src/add-ons/kernel/network/stack/domains.cpp index bc1c019142..d4a8b7bfac 100644 --- a/src/add-ons/kernel/network/stack/domains.cpp +++ b/src/add-ons/kernel/network/stack/domains.cpp @@ -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); diff --git a/src/add-ons/kernel/network/stack/interfaces.cpp b/src/add-ons/kernel/network/stack/interfaces.cpp index 5ffb859b2e..33b60d25f0 100644 --- a/src/add-ons/kernel/network/stack/interfaces.cpp +++ b/src/add-ons/kernel/network/stack/interfaces.cpp @@ -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); diff --git a/src/add-ons/kernel/network/stack/interfaces.h b/src/add-ons/kernel/network/stack/interfaces.h index a9345cba0b..bca96f5794 100644 --- a/src/add-ons/kernel/network/stack/interfaces.h +++ b/src/add-ons/kernel/network/stack/interfaces.h @@ -42,7 +42,7 @@ struct net_device_interface : DoublyLinkedListLinkImpl { DeviceMonitorList monitor_funcs; DeviceHandlerList receive_funcs; - benaphore rx_lock; + recursive_lock rx_lock; }; typedef DoublyLinkedList DeviceInterfaceList;