From dff920765002d07c2275ef390368fc43bc08f00b Mon Sep 17 00:00:00 2001
From: Stefano Ceccherini <stefano.ceccherini@gmail.com>
Date: Sat, 6 Sep 2014 21:13:19 +0200
Subject: [PATCH 1/2] Change the monitor_lock to be a recursive_lock, fixing
#7039. notify_device_monitor acquires the monitor lock, then tells the
monitor to unregister itself, calling unregister_device_monitor, which
acquires the monitor lock again.
---
src/add-ons/kernel/network/stack/device_interfaces.cpp | 16 ++++++++--------
src/add-ons/kernel/network/stack/device_interfaces.h | 2 +-
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/src/add-ons/kernel/network/stack/device_interfaces.cpp b/src/add-ons/kernel/network/stack/device_interfaces.cpp
index a3030f0..0143360 100644
a
|
b
|
allocate_device_interface(net_device* device, net_device_module_info* module)
|
171 | 171 | return NULL; |
172 | 172 | |
173 | 173 | recursive_lock_init(&interface->receive_lock, "device interface receive"); |
174 | | mutex_init(&interface->monitor_lock, "device interface monitors"); |
| 174 | recursive_lock_init(&interface->monitor_lock, "device interface monitors"); |
175 | 175 | |
176 | 176 | char name[128]; |
177 | 177 | snprintf(name, sizeof(name), "%s receive queue", device->name); |
… |
… |
error2:
|
206 | 206 | uninit_fifo(&interface->receive_queue); |
207 | 207 | error1: |
208 | 208 | recursive_lock_destroy(&interface->receive_lock); |
209 | | mutex_destroy(&interface->monitor_lock); |
| 209 | recursive_lock_destroy(&interface->monitor_lock); |
210 | 210 | delete interface; |
211 | 211 | |
212 | 212 | return NULL; |
… |
… |
error1:
|
216 | 216 | static void |
217 | 217 | notify_device_monitors(net_device_interface* interface, int32 event) |
218 | 218 | { |
219 | | MutexLocker locker(interface->monitor_lock); |
| 219 | RecursiveLocker locker(interface->monitor_lock); |
220 | 220 | |
221 | 221 | DeviceMonitorList::Iterator iterator |
222 | 222 | = interface->monitor_funcs.GetIterator(); |
… |
… |
put_device_interface(struct net_device_interface* interface)
|
392 | 392 | device->module->uninit_device(device); |
393 | 393 | put_module(moduleName); |
394 | 394 | |
395 | | mutex_destroy(&interface->monitor_lock); |
| 395 | recursive_lock_destroy(&interface->monitor_lock); |
396 | 396 | recursive_lock_destroy(&interface->receive_lock); |
397 | 397 | delete interface; |
398 | 398 | } |
… |
… |
void
|
478 | 478 | device_interface_monitor_receive(net_device_interface* interface, |
479 | 479 | net_buffer* buffer) |
480 | 480 | { |
481 | | MutexLocker locker(interface->monitor_lock); |
| 481 | RecursiveLocker locker(interface->monitor_lock); |
482 | 482 | |
483 | 483 | DeviceMonitorList::Iterator iterator |
484 | 484 | = interface->monitor_funcs.GetIterator(); |
… |
… |
register_device_monitor(net_device* device, net_device_monitor* monitor)
|
706 | 706 | if (interface == NULL) |
707 | 707 | return B_DEVICE_NOT_FOUND; |
708 | 708 | |
709 | | MutexLocker monitorLocker(interface->monitor_lock); |
| 709 | RecursiveLocker monitorLocker(interface->monitor_lock); |
710 | 710 | interface->monitor_funcs.Add(monitor); |
711 | 711 | atomic_add(&interface->monitor_count, 1); |
712 | 712 | |
… |
… |
unregister_device_monitor(net_device* device, net_device_monitor* monitor)
|
725 | 725 | if (interface == NULL) |
726 | 726 | return B_DEVICE_NOT_FOUND; |
727 | 727 | |
728 | | MutexLocker monitorLocker(interface->monitor_lock); |
| 728 | RecursiveLocker monitorLocker(interface->monitor_lock); |
729 | 729 | |
730 | 730 | // search for the monitor |
731 | 731 | |
… |
… |
device_removed(net_device* device)
|
776 | 776 | |
777 | 777 | // By now all of the monitors must have removed themselves. If they |
778 | 778 | // didn't, they'll probably wait forever to be callback'ed again. |
779 | | mutex_lock(&interface->monitor_lock); |
| 779 | recursive_lock_lock(&interface->monitor_lock); |
780 | 780 | interface->monitor_funcs.RemoveAll(); |
781 | 781 | |
782 | 782 | // All of the readers should be gone as well since we are out of |
diff --git a/src/add-ons/kernel/network/stack/device_interfaces.h b/src/add-ons/kernel/network/stack/device_interfaces.h
index 6dcc4c0..958448e 100644
a
|
b
|
struct net_device_interface : DoublyLinkedListLinkImpl<net_device_interface> {
|
37 | 37 | int32 deframe_ref_count; |
38 | 38 | |
39 | 39 | int32 monitor_count; |
40 | | mutex monitor_lock; |
| 40 | recursive_lock monitor_lock; |
41 | 41 | DeviceMonitorList monitor_funcs; |
42 | 42 | |
43 | 43 | DeviceHandlerList receive_funcs; |