Rework DefaultNotificationService registration.
- Instead of implicitly registering and unregistering a service instance on construction/destruction, DefaultNotificationService now exports explicit Register()/Unregister() calls, which subclasses are expected to call when they're ready. - Adjust all implementing subclasses. Resolves an issue with deadlocks when booting a DEBUG=1 build.
This commit is contained in:
@@ -152,6 +152,9 @@ public:
|
|||||||
|
|
||||||
virtual const char* Name() { return fName; }
|
virtual const char* Name() { return fName; }
|
||||||
|
|
||||||
|
status_t Register();
|
||||||
|
void Unregister();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual status_t ToEventMask(const KMessage& eventSpecifier,
|
virtual status_t ToEventMask(const KMessage& eventSpecifier,
|
||||||
uint32& eventMask);
|
uint32& eventMask);
|
||||||
|
|||||||
@@ -130,22 +130,32 @@ notifications_std_ops(int32 op, ...)
|
|||||||
{
|
{
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case B_MODULE_INIT:
|
case B_MODULE_INIT:
|
||||||
|
{
|
||||||
TRACE("init\n");
|
TRACE("init\n");
|
||||||
|
|
||||||
new(&sNotificationService) NetNotificationService();
|
new(&sNotificationService) NetNotificationService();
|
||||||
|
status_t result = sNotificationService.Register();
|
||||||
|
if (result != B_OK)
|
||||||
|
return result;
|
||||||
|
|
||||||
register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
|
register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
|
||||||
net_notifications_control, 1, 0);
|
net_notifications_control, 1, 0);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
}
|
||||||
case B_MODULE_UNINIT:
|
case B_MODULE_UNINIT:
|
||||||
TRACE("uninit\n");
|
TRACE("uninit\n");
|
||||||
|
|
||||||
unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
|
unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
|
||||||
|
|
||||||
|
// TODO: due to the way the locking in the notification
|
||||||
|
// manager works, there's a potential race condition here
|
||||||
|
// where someone attempts to add a listener right as
|
||||||
|
// we're uninitializing. Needs to be looked at/resolved.
|
||||||
|
sNotificationService.Unregister();
|
||||||
|
|
||||||
// we need to release the reference that was acquired
|
// we need to release the reference that was acquired
|
||||||
// on our behalf by the NotificationManager.
|
// on our behalf by the NotificationManager.
|
||||||
// sNotificationService.ReleaseReference();
|
sNotificationService.ReleaseReference();
|
||||||
sNotificationService.~NetNotificationService();
|
sNotificationService.~NetNotificationService();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
|||||||
@@ -156,13 +156,11 @@ DefaultNotificationService::DefaultNotificationService(const char* name)
|
|||||||
fName(name)
|
fName(name)
|
||||||
{
|
{
|
||||||
recursive_lock_init(&fLock, name);
|
recursive_lock_init(&fLock, name);
|
||||||
NotificationManager::Manager().RegisterService(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
DefaultNotificationService::~DefaultNotificationService()
|
DefaultNotificationService::~DefaultNotificationService()
|
||||||
{
|
{
|
||||||
NotificationManager::Manager().UnregisterService(*this);
|
|
||||||
recursive_lock_destroy(&fLock);
|
recursive_lock_destroy(&fLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,6 +251,20 @@ DefaultNotificationService::RemoveListener(const KMessage* eventSpecifier,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
DefaultNotificationService::Register()
|
||||||
|
{
|
||||||
|
return NotificationManager::Manager().RegisterService(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
DefaultNotificationService::Unregister()
|
||||||
|
{
|
||||||
|
NotificationManager::Manager().UnregisterService(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
DefaultNotificationService::ToEventMask(const KMessage& eventSpecifier,
|
DefaultNotificationService::ToEventMask(const KMessage& eventSpecifier,
|
||||||
uint32& eventMask)
|
uint32& eventMask)
|
||||||
|
|||||||
@@ -78,10 +78,12 @@ IOSchedulerRoster::IOSchedulerRoster()
|
|||||||
fNotificationService("I/O")
|
fNotificationService("I/O")
|
||||||
{
|
{
|
||||||
mutex_init(&fLock, "IOSchedulerRoster");
|
mutex_init(&fLock, "IOSchedulerRoster");
|
||||||
|
fNotificationService.Register();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IOSchedulerRoster::~IOSchedulerRoster()
|
IOSchedulerRoster::~IOSchedulerRoster()
|
||||||
{
|
{
|
||||||
mutex_destroy(&fLock);
|
mutex_destroy(&fLock);
|
||||||
|
fNotificationService.Unregister();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,6 +254,8 @@ KDiskDeviceManager::KDiskDeviceManager()
|
|||||||
if (InitCheck() != B_OK)
|
if (InitCheck() != B_OK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
fNotifications->Register();
|
||||||
|
|
||||||
RescanDiskSystems();
|
RescanDiskSystems();
|
||||||
|
|
||||||
fMediaChecker = spawn_kernel_thread(_CheckMediaStatusDaemon,
|
fMediaChecker = spawn_kernel_thread(_CheckMediaStatusDaemon,
|
||||||
@@ -310,6 +312,8 @@ KDiskDeviceManager::~KDiskDeviceManager()
|
|||||||
delete diskSystem;
|
delete diskSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fNotifications->Unregister();
|
||||||
|
|
||||||
// delete the containers
|
// delete the containers
|
||||||
delete fPartitions;
|
delete fPartitions;
|
||||||
delete fDevices;
|
delete fDevices;
|
||||||
|
|||||||
@@ -343,6 +343,8 @@ image_init(void)
|
|||||||
|
|
||||||
new(&sNotificationService) ImageNotificationService();
|
new(&sNotificationService) ImageNotificationService();
|
||||||
|
|
||||||
|
sNotificationService.Register();
|
||||||
|
|
||||||
#ifdef ADD_DEBUGGER_COMMANDS
|
#ifdef ADD_DEBUGGER_COMMANDS
|
||||||
add_debugger_command("team_images", &dump_images_list, "Dump all registered images from the current team");
|
add_debugger_command("team_images", &dump_images_list, "Dump all registered images from the current team");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -792,6 +792,7 @@ port_init(kernel_args *args)
|
|||||||
" <condition> - address of the port's read or write condition.\n", 0);
|
" <condition> - address of the port's read or write condition.\n", 0);
|
||||||
|
|
||||||
new(&sNotificationService) PortNotificationService();
|
new(&sNotificationService) PortNotificationService();
|
||||||
|
sNotificationService.Register();
|
||||||
sPortsActive = true;
|
sPortsActive = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2771,6 +2771,8 @@ team_init(kernel_args* args)
|
|||||||
|
|
||||||
new(&sNotificationService) TeamNotificationService();
|
new(&sNotificationService) TeamNotificationService();
|
||||||
|
|
||||||
|
sNotificationService.Register();
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2738,6 +2738,8 @@ thread_init(kernel_args *args)
|
|||||||
// init the notification service
|
// init the notification service
|
||||||
new(&sNotificationService) ThreadNotificationService();
|
new(&sNotificationService) ThreadNotificationService();
|
||||||
|
|
||||||
|
sNotificationService.Register();
|
||||||
|
|
||||||
// start the undertaker thread
|
// start the undertaker thread
|
||||||
new(&sUndertakerEntries) DoublyLinkedList<UndertakerEntry>();
|
new(&sUndertakerEntries) DoublyLinkedList<UndertakerEntry>();
|
||||||
sUndertakerCondition.Init(&sUndertakerEntries, "undertaker entries");
|
sUndertakerCondition.Init(&sUndertakerEntries, "undertaker entries");
|
||||||
|
|||||||
Reference in New Issue
Block a user