* Added DefaultNotificationService and DefaultUserNotificationService

implementations that can be used by subsystems that want to have a pretty
  standard service. Only the latter is really complete, though.
* The notification manager is now available earlier in the boot process.
* Added notifications to teams/ports (only add/remove).
* The network notification implementation is now using the
  DefaultUserNotificationService.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29543 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2009-03-15 10:21:56 +00:00
parent d60fa63b38
commit 51755cf832
8 changed files with 632 additions and 319 deletions
+174 -85
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Copyright 2007-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -29,124 +29,213 @@
class NotificationService;
class NotificationListener {
public:
virtual ~NotificationListener();
public:
virtual ~NotificationListener();
virtual void EventOccured(NotificationService& service,
const KMessage* event);
virtual void AllListenersNotified(NotificationService& service);
virtual void EventOccured(NotificationService& service,
const KMessage* event);
virtual void AllListenersNotified(
NotificationService& service);
virtual bool operator==(const NotificationListener& other) const;
virtual bool operator==(
const NotificationListener& other) const;
bool operator!=(const NotificationListener& other) const
{ return !(*this == other); }
bool operator!=(
const NotificationListener& other) const
{ return !(*this == other); }
};
class UserMessagingMessageSender {
public:
UserMessagingMessageSender();
public:
UserMessagingMessageSender();
void SendMessage(const KMessage* message, port_id port, int32 token);
void FlushMessage();
void SendMessage(const KMessage* message,
port_id port, int32 token);
void FlushMessage();
private:
enum {
MAX_MESSAGING_TARGET_COUNT = 16,
};
private:
enum {
MAX_MESSAGING_TARGET_COUNT = 16,
};
const KMessage* fMessage;
messaging_target fTargets[MAX_MESSAGING_TARGET_COUNT];
int32 fTargetCount;
const KMessage* fMessage;
messaging_target fTargets[MAX_MESSAGING_TARGET_COUNT];
int32 fTargetCount;
};
class UserMessagingListener : public NotificationListener {
public:
UserMessagingListener(UserMessagingMessageSender& sender, port_id port,
int32 token);
virtual ~UserMessagingListener();
public:
UserMessagingListener(
UserMessagingMessageSender& sender,
port_id port, int32 token);
virtual ~UserMessagingListener();
virtual void EventOccured(NotificationService& service,
const KMessage* event);
virtual void AllListenersNotified(NotificationService& service);
virtual void EventOccured(NotificationService& service,
const KMessage* event);
virtual void AllListenersNotified(
NotificationService& service);
port_id Port() const { return fPort; }
int32 Token() const { return fToken; }
port_id Port() const { return fPort; }
int32 Token() const { return fToken; }
private:
UserMessagingMessageSender& fSender;
port_id fPort;
int32 fToken;
bool operator==(
const NotificationListener& _other) const;
private:
UserMessagingMessageSender& fSender;
port_id fPort;
int32 fToken;
};
inline bool
UserMessagingListener::operator==(const NotificationListener& _other) const
{
const UserMessagingListener* other
= dynamic_cast<const UserMessagingListener*>(&_other);
return other != NULL && other->Port() == Port()
&& other->Token() == Token();
}
class NotificationService : public Referenceable {
public:
virtual ~NotificationService();
public:
virtual ~NotificationService();
virtual status_t AddListener(const KMessage* eventSpecifier,
NotificationListener& listener) = 0;
virtual status_t RemoveListener(const KMessage* eventSpecifier,
NotificationListener& listener) = 0;
virtual status_t UpdateListener(const KMessage* eventSpecifier,
NotificationListener& listener) = 0;
virtual status_t AddListener(const KMessage* eventSpecifier,
NotificationListener& listener) = 0;
virtual status_t RemoveListener(const KMessage* eventSpecifier,
NotificationListener& listener) = 0;
virtual status_t UpdateListener(const KMessage* eventSpecifier,
NotificationListener& listener) = 0;
virtual const char* Name() = 0;
HashTableLink<NotificationService>& Link() { return fLink; }
virtual const char* Name() = 0;
HashTableLink<NotificationService>&
Link() { return fLink; }
private:
HashTableLink<NotificationService> fLink;
private:
HashTableLink<NotificationService> fLink;
};
struct default_listener : public DoublyLinkedListLinkImpl<default_listener> {
~default_listener();
uint32 flags;
team_id team;
NotificationListener* listener;
};
typedef DoublyLinkedList<default_listener> DefaultListenerList;
class DefaultNotificationService : public NotificationService {
public:
DefaultNotificationService(const char* name);
virtual ~DefaultNotificationService();
void Notify(const KMessage& event, uint32 flags);
virtual status_t AddListener(const KMessage* eventSpecifier,
NotificationListener& listener);
virtual status_t UpdateListener(const KMessage* eventSpecifier,
NotificationListener& listener);
virtual status_t RemoveListener(const KMessage* eventSpecifier,
NotificationListener& listener);
virtual const char* Name() { return fName; }
protected:
virtual status_t _ToFlags(const KMessage& eventSpecifier,
uint32& flags);
virtual void _FirstAdded();
virtual void _LastRemoved();
recursive_lock fLock;
DefaultListenerList fListeners;
const char* fName;
};
class DefaultUserNotificationService : public DefaultNotificationService,
NotificationListener {
public:
DefaultUserNotificationService(
const char* name);
virtual ~DefaultUserNotificationService();
virtual status_t AddListener(const KMessage* eventSpecifier,
NotificationListener& listener);
virtual status_t UpdateListener(const KMessage* eventSpecifier,
NotificationListener& listener);
virtual status_t RemoveListener(const KMessage* eventSpecifier,
NotificationListener& listener);
status_t RemoveUserListeners(port_id port, uint32 token);
status_t UpdateUserListener(uint32 flags,
port_id port, uint32 token);
private:
virtual void EventOccured(NotificationService& service,
const KMessage* event);
virtual void AllListenersNotified(
NotificationService& service);
status_t _AddListener(uint32 flags,
NotificationListener& listener);
UserMessagingMessageSender fSender;
};
class NotificationManager {
public:
static NotificationManager& Manager();
static status_t CreateManager();
public:
static NotificationManager& Manager();
static status_t CreateManager();
status_t RegisterService(NotificationService& service);
void UnregisterService(NotificationService& service);
status_t RegisterService(NotificationService& service);
void UnregisterService(
NotificationService& service);
NotificationService* GetService(const char* name);
void PutService(NotificationService* service);
status_t AddListener(const char* service,
uint32 eventMask,
NotificationListener& listener);
status_t AddListener(const char* service,
const KMessage* eventSpecifier,
NotificationListener& listener);
status_t AddListener(const char* service, uint32 eventMask,
NotificationListener& listener);
status_t AddListener(const char* service,
const KMessage* eventSpecifier, NotificationListener& listener);
status_t UpdateListener(const char* service,
uint32 eventMask,
NotificationListener& listener);
status_t UpdateListener(const char* service,
const KMessage* eventSpecifier,
NotificationListener& listener);
status_t UpdateListener(const char* service,
uint32 eventMask, NotificationListener& listener);
status_t UpdateListener(const char* service,
const KMessage* eventSpecifier, NotificationListener& listener);
status_t RemoveListener(const char* service,
const KMessage* eventSpecifier,
NotificationListener& listener);
status_t RemoveListener(const char* service,
const KMessage* eventSpecifier, NotificationListener& listener);
private:
NotificationManager();
~NotificationManager();
private:
NotificationManager();
~NotificationManager();
status_t _Init();
NotificationService* _ServiceFor(const char* name);
status_t _Init();
NotificationService* _ServiceFor(const char* name);
struct HashDefinition {
typedef const char* KeyType;
typedef NotificationService ValueType;
struct HashDefinition {
typedef const char* KeyType;
typedef NotificationService ValueType;
size_t HashKey(const char* key) const
{ return hash_hash_string(key); }
size_t Hash(NotificationService *service) const
{ return hash_hash_string(service->Name()); }
bool Compare(const char* key, NotificationService* service) const
{ return !strcmp(key, service->Name()); }
HashTableLink<NotificationService>* GetLink(
NotificationService* service) const
{ return &service->Link(); }
};
typedef OpenHashTable<HashDefinition> ServiceHash;
size_t HashKey(const char* key) const
{ return hash_hash_string(key); }
size_t Hash(NotificationService *service) const
{ return hash_hash_string(service->Name()); }
bool Compare(const char* key, NotificationService* service) const
{ return !strcmp(key, service->Name()); }
HashTableLink<NotificationService>* GetLink(
NotificationService* service) const
{ return &service->Link(); }
};
static NotificationManager sManager;
static NotificationManager sManager;
mutex fLock;
typedef OpenHashTable<HashDefinition> ServiceHash;
ServiceHash fServiceHash;
mutex fLock;
ServiceHash fServiceHash;
};
extern "C" {
+5 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2005, Haiku Inc. All Rights Reserved.
* Copyright 2005-2009, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT license.
*/
#ifndef _KERNEL_PORT_H
@@ -22,6 +22,10 @@ enum {
// kernel-only; memory must be locked
};
// port notifications
#define PORT_MONITOR '_Pm_'
#define PORT_ADDED 1
#define PORT_REMOVED 2
#ifdef __cplusplus
extern "C" {
+7 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2004-2007, Haiku Inc. All Rights Reserved.
* Copyright 2004-2009, Haiku Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _TEAM_H
@@ -9,6 +9,12 @@
#include <thread_types.h>
// Team notifications
#define TEAM_MONITOR '_Tm_'
#define TEAM_ADDED 1
#define TEAM_REMOVED 2
#ifdef __cplusplus
extern "C" {
#endif
@@ -18,95 +18,38 @@
# define TRACE(x...) ;
#endif
// TODO: add possibility to remove teams/ports that are gone
static UserMessagingMessageSender sNotificationSender;
struct net_listener : public DoublyLinkedListLinkImpl<net_listener> {
~net_listener();
uint32 flags;
NotificationListener* listener;
};
typedef DoublyLinkedList<net_listener> ListenerList;
class UserNetListener : public UserMessagingListener {
public:
UserNetListener(port_id port, int32 token)
: UserMessagingListener(sNotificationSender, port, token)
{
}
bool operator==(const NotificationListener& _other) const
{
const UserNetListener* other
= dynamic_cast<const UserNetListener*>(&_other);
return other != NULL && other->Port() == Port()
&& other->Token() == Token();
}
};
class NetNotificationService : public NotificationService {
class NetNotificationService : public DefaultUserNotificationService {
public:
NetNotificationService();
virtual ~NetNotificationService();
void Notify(const KMessage& event);
status_t AddListener(const KMessage* eventSpecifier,
NotificationListener& listener);
status_t UpdateListener(const KMessage* eventSpecifier,
NotificationListener& listener);
status_t RemoveListener(const KMessage* eventSpecifier,
NotificationListener& listener);
status_t RemoveUserListeners(port_id port, uint32 token);
status_t UpdateUserListener(uint32 flags,
port_id port, uint32 token);
virtual const char* Name() { return "network"; }
private:
status_t _AddListener(uint32 flags,
NotificationListener& listener);
recursive_lock fRecursiveLock;
ListenerList fListeners;
protected:
virtual status_t _ToFlags(const KMessage& eventSpecifier,
uint32& flags);
virtual void _FirstAdded();
virtual void _LastRemoved();
};
static NetNotificationService sNotificationService;
net_listener::~net_listener()
{
// Only delete the listener if it's one of ours
if (dynamic_cast<UserNetListener*>(listener) != NULL) {
TRACE("delete user listener %p\n", listener);
delete listener;
}
}
// #pragma mark - NetNotificationService
NetNotificationService::NetNotificationService()
: DefaultUserNotificationService("network")
{
recursive_lock_init(&fRecursiveLock, "net notifications");
}
NetNotificationService::~NetNotificationService()
{
recursive_lock_destroy(&fRecursiveLock);
}
/*! \brief Notifies all registered listeners.
\param event The message defining the event
*/
void
NetNotificationService::Notify(const KMessage& event)
{
@@ -116,173 +59,36 @@ NetNotificationService::Notify(const KMessage& event)
TRACE("notify for %lx\n", opcode);
RecursiveLocker _(fRecursiveLock);
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if ((listener->flags & opcode) != 0) {
TRACE(" notify listener %p for %lx\n", listener, opcode);
listener->listener->EventOccured(*this, &event);
}
}
iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if ((listener->flags & opcode) != 0)
listener->listener->AllListenersNotified(*this);
}
DefaultUserNotificationService::Notify(event, opcode);
}
status_t
NetNotificationService::AddListener(const KMessage* eventSpecifier,
NotificationListener& listener)
NetNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
if (eventSpecifier == NULL)
return B_BAD_VALUE;
uint32 flags = eventSpecifier->GetInt32("flags", 0);
return _AddListener(flags, listener);
}
status_t
NetNotificationService::UpdateListener(const KMessage* eventSpecifier,
NotificationListener& notificationListener)
{
if (eventSpecifier == NULL)
return B_BAD_VALUE;
uint32 flags = eventSpecifier->GetInt32("flags", 0);
bool addFlags = eventSpecifier->GetBool("add flags", false);
RecursiveLocker _(fRecursiveLock);
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if (*listener->listener == notificationListener) {
if (addFlags)
listener->flags |= flags;
else
listener->flags = flags;
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
NetNotificationService::RemoveListener(const KMessage* eventSpecifier,
NotificationListener& notificationListener)
{
RecursiveLocker _(fRecursiveLock);
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if (listener->listener == &notificationListener) {
TRACE("remove listener %p\n", listener);
iterator.Remove();
delete listener;
if (fListeners.IsEmpty()) {
// Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
NetNotificationService::RemoveUserListeners(port_id port, uint32 token)
{
UserNetListener userListener(port, token);
RecursiveLocker _(fRecursiveLock);
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if (*listener->listener == userListener) {
TRACE("remove user listener %p\n", listener);
iterator.Remove();
delete listener;
if (fListeners.IsEmpty()) {
// Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
NetNotificationService::UpdateUserListener(uint32 flags, port_id port,
uint32 token)
{
UserNetListener userListener(port, token);
RecursiveLocker _(fRecursiveLock);
ListenerList::Iterator iterator = fListeners.GetIterator();
while (net_listener* listener = iterator.Next()) {
if (*listener->listener == userListener) {
listener->flags |= flags;
return B_OK;
}
}
UserNetListener* copiedListener = new(std::nothrow) UserNetListener(
userListener);
if (copiedListener == NULL)
return B_NO_MEMORY;
status_t status = _AddListener(flags, *copiedListener);
if (status != B_OK)
delete copiedListener;
return status;
}
status_t
NetNotificationService::_AddListener(uint32 flags,
NotificationListener& notificationListener)
{
net_listener* listener = new(std::nothrow) net_listener;
if (listener == NULL)
return B_NO_MEMORY;
TRACE("add %slistener %p for %lx\n",
dynamic_cast<UserNetListener*>(&notificationListener) != NULL
? "user " : "", listener, flags);
listener->flags = flags;
listener->listener = &notificationListener;
RecursiveLocker _(fRecursiveLock);
if (fListeners.IsEmpty()) {
// The reference counting doesn't work for us, as we'll have to
// ensure our module stays loaded.
module_info* dummy;
get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy);
}
fListeners.Add(listener);
flags = eventSpecifier.GetInt32("flags", 0);
return B_OK;
}
void
NetNotificationService::_FirstAdded()
{
// The reference counting doesn't work for us, as we'll have to
// ensure our module stays loaded.
module_info* dummy;
get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy);
}
void
NetNotificationService::_LastRemoved()
{
// Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME);
}
// #pragma mark - User generic syscall
@@ -326,7 +132,6 @@ notifications_std_ops(int32 op, ...)
case B_MODULE_INIT:
TRACE("init\n");
new(&sNotificationSender) UserMessagingMessageSender();
new(&sNotificationService) NetNotificationService();
register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
@@ -338,7 +143,6 @@ notifications_std_ops(int32 op, ...)
unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
sNotificationSender.~UserMessagingMessageSender();
sNotificationService.~NetNotificationService();
return B_OK;
+314 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2007, Haiku, Inc. All Rights Reserved.
* Copyright 2007-2009, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
@@ -10,11 +10,13 @@
#include <Notifications.h>
#include <team.h>
NotificationManager NotificationManager::sManager;
// #pragma mark - UserMessagingListener
// #pragma mark - NotificationListener
NotificationListener::~NotificationListener()
@@ -123,6 +125,316 @@ NotificationService::~NotificationService()
}
// #pragma mark - default_listener
default_listener::~default_listener()
{
// Only delete the listener if it's one of ours
if (dynamic_cast<UserMessagingListener*>(listener) != NULL) {
delete listener;
}
}
// #pragma mark - NotificationService
DefaultNotificationService::DefaultNotificationService(const char* name)
:
fName(name)
{
recursive_lock_init(&fLock, name);
NotificationManager::Manager().RegisterService(*this);
}
DefaultNotificationService::~DefaultNotificationService()
{
NotificationManager::Manager().UnregisterService(*this);
recursive_lock_destroy(&fLock);
}
/*! \brief Notifies all registered listeners.
\param event The message defining the event
\param flags The flags that must be set in listeners to receive this event
*/
void
DefaultNotificationService::Notify(const KMessage& event, uint32 flags)
{
RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if ((flags & listener->flags) != 0)
listener->listener->EventOccured(*this, &event);
}
iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if ((flags & listener->flags) != 0)
listener->listener->AllListenersNotified(*this);
}
}
status_t
DefaultNotificationService::AddListener(const KMessage* eventSpecifier,
NotificationListener& notificationListener)
{
if (eventSpecifier == NULL)
return B_BAD_VALUE;
uint32 flags;
status_t status = _ToFlags(*eventSpecifier, flags);
if (status != B_OK)
return status;
default_listener* listener = new(std::nothrow) default_listener;
if (listener == NULL)
return B_NO_MEMORY;
listener->flags = flags;
listener->team = -1;
listener->listener = &notificationListener;
RecursiveLocker _(fLock);
if (fListeners.IsEmpty())
_FirstAdded();
fListeners.Add(listener);
return B_OK;
}
status_t
DefaultNotificationService::UpdateListener(const KMessage* eventSpecifier,
NotificationListener& notificationListener)
{
return B_NOT_SUPPORTED;
}
status_t
DefaultNotificationService::RemoveListener(const KMessage* eventSpecifier,
NotificationListener& notificationListener)
{
RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if (listener->listener == &notificationListener) {
iterator.Remove();
delete listener;
if (fListeners.IsEmpty())
_LastRemoved();
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
DefaultNotificationService::_ToFlags(const KMessage& eventSpecifier,
uint32& flags)
{
return eventSpecifier.FindInt32("flags", (int32*)&flags);
}
void
DefaultNotificationService::_FirstAdded()
{
}
void
DefaultNotificationService::_LastRemoved()
{
}
// #pragma mark - DefaultUserNotificationService
DefaultUserNotificationService::DefaultUserNotificationService(const char* name)
: DefaultNotificationService(name)
{
NotificationManager::Manager().AddListener("teams", TEAM_REMOVED, *this);
}
DefaultUserNotificationService::~DefaultUserNotificationService()
{
NotificationManager::Manager().RemoveListener("teams", NULL, *this);
}
status_t
DefaultUserNotificationService::AddListener(const KMessage* eventSpecifier,
NotificationListener& listener)
{
if (eventSpecifier == NULL)
return B_BAD_VALUE;
uint32 flags = eventSpecifier->GetInt32("flags", 0);
return _AddListener(flags, listener);
}
status_t
DefaultUserNotificationService::UpdateListener(const KMessage* eventSpecifier,
NotificationListener& notificationListener)
{
if (eventSpecifier == NULL)
return B_BAD_VALUE;
uint32 flags = eventSpecifier->GetInt32("flags", 0);
bool addFlags = eventSpecifier->GetBool("add flags", false);
RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if (*listener->listener == notificationListener) {
if (addFlags)
listener->flags |= flags;
else
listener->flags = flags;
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
DefaultUserNotificationService::RemoveListener(const KMessage* eventSpecifier,
NotificationListener& notificationListener)
{
RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if (listener->listener == &notificationListener) {
iterator.Remove();
delete listener;
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
DefaultUserNotificationService::RemoveUserListeners(port_id port, uint32 token)
{
UserMessagingListener userListener(fSender, port, token);
RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if (*listener->listener == userListener) {
iterator.Remove();
delete listener;
if (fListeners.IsEmpty())
_LastRemoved();
return B_OK;
}
}
return B_ENTRY_NOT_FOUND;
}
status_t
DefaultUserNotificationService::UpdateUserListener(uint32 flags, port_id port,
uint32 token)
{
UserMessagingListener userListener(fSender, port, token);
RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if (*listener->listener == userListener) {
listener->flags |= flags;
return B_OK;
}
}
UserMessagingListener* copiedListener
= new(std::nothrow) UserMessagingListener(userListener);
if (copiedListener == NULL)
return B_NO_MEMORY;
status_t status = _AddListener(flags, *copiedListener);
if (status != B_OK)
delete copiedListener;
return status;
}
void
DefaultUserNotificationService::EventOccured(NotificationService& service,
const KMessage* event)
{
int32 opcode = event->GetInt32("opcode", -1);
team_id team = event->GetInt32("team", -1);
if (opcode == TEAM_REMOVED && team >= B_OK) {
// check if we have any listeners from that team, and remove them
RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) {
if (listener->team == team) {
iterator.Remove();
delete listener;
}
}
}
}
void
DefaultUserNotificationService::AllListenersNotified(
NotificationService& service)
{
}
status_t
DefaultUserNotificationService::_AddListener(uint32 flags,
NotificationListener& notificationListener)
{
default_listener* listener = new(std::nothrow) default_listener;
if (listener == NULL)
return B_NO_MEMORY;
listener->flags = flags;
listener->team = team_get_current_team_id();
listener->listener = &notificationListener;
RecursiveLocker _(fLock);
if (fListeners.IsEmpty())
_FirstAdded();
fListeners.Add(listener);
return B_OK;
}
// #pragma mark - NotificationManager
+2 -2
View File
@@ -130,6 +130,8 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
boot_item_init();
driver_settings_init(&sKernelArgs);
debug_init_post_vm(&sKernelArgs);
TRACE("init notification services\n");
notifications_init();
TRACE("init teams\n");
team_init(&sKernelArgs);
TRACE("init ELF loader\n");
@@ -180,8 +182,6 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
TRACE("init VM threads\n");
vm_init_post_thread(&sKernelArgs);
low_resource_manager_init_post_thread();
TRACE("init notification services\n");
notifications_init();
TRACE("init VFS\n");
vfs_init(&sKernelArgs);
#if ENABLE_SWAP_SUPPORT
+53 -3
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007, Axel Dörfler, axeld@pinc-software.de.
* Copyright 2002-2009, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001, Mark-Jan Bastian. All rights reserved.
@@ -20,6 +20,7 @@
#include <arch/int.h>
#include <cbuf.h>
#include <kernel.h>
#include <Notifications.h>
#include <sem.h>
#include <syscall_restart.h>
#include <team.h>
@@ -59,6 +60,16 @@ struct port_entry {
struct list msg_queue;
};
class PortNotificationService : public DefaultNotificationService {
public:
PortNotificationService();
void Notify(uint32 opcode, port_id team);
protected:
virtual status_t _ToFlags(const KMessage& eventSpecifier,
uint32& flags);
};
#define MAX_QUEUE_LENGTH 4096
#define PORT_MAX_MESSAGE_SIZE (256 * 1024)
@@ -73,6 +84,8 @@ static bool sPortsActive = false;
static port_id sNextPort = 1;
static int32 sFirstFreeSlot = 1;
static PortNotificationService sNotificationService;
static spinlock sPortSpinlock = B_SPINLOCK_INITIALIZER;
#define GRAB_PORT_LIST_LOCK() acquire_spinlock(&sPortSpinlock)
@@ -81,6 +94,39 @@ static spinlock sPortSpinlock = B_SPINLOCK_INITIALIZER;
#define RELEASE_PORT_LOCK(s) release_spinlock(&(s).lock)
// #pragma mark - TeamNotificationService
PortNotificationService::PortNotificationService()
: DefaultNotificationService("ports")
{
}
void
PortNotificationService::Notify(uint32 opcode, port_id port)
{
char eventBuffer[64];
KMessage event;
event.SetTo(eventBuffer, sizeof(eventBuffer), PORT_MONITOR);
event.AddInt32("opcode", opcode);
event.AddInt32("port", port);
DefaultNotificationService::Notify(event, ~0U);
}
status_t
PortNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
flags = ~0U;
return B_OK;
}
// #pragma mark -
static int
dump_port_list(int argc, char **argv)
{
@@ -362,6 +408,7 @@ port_init(kernel_args *args)
" <name> - Name of the port.\n"
" <sem> - ID of the port's read or write semaphore.\n", 0);
new(&sNotificationService) PortNotificationService();
sPortsActive = true;
return B_OK;
}
@@ -380,7 +427,8 @@ create_port(int32 queueLength, const char *name)
team_id owner;
int32 slot;
TRACE(("create_port(queueLength = %ld, name = \"%s\")\n", queueLength, name));
TRACE(("create_port(queueLength = %ld, name = \"%s\")\n", queueLength,
name));
if (!sPortsActive)
return B_BAD_PORT_ID;
@@ -463,13 +511,14 @@ create_port(int32 queueLength, const char *name)
TRACE(("create_port() done: port created %ld\n", id));
sNotificationService.Notify(PORT_ADDED, id);
return id;
}
}
// not enough ports...
// ToDo: due to sUsedPorts, this cannot happen anymore - as
// TODO: due to sUsedPorts, this cannot happen anymore - as
// long as sMaxPorts stays constant over the kernel run
// time (which it should be). IOW we could simply panic()
// here.
@@ -597,6 +646,7 @@ delete_port(port_id id)
// read_port() will see the B_BAD_SEM_ID acq_sem() return value, and act accordingly
delete_sem(readSem);
delete_sem(writeSem);
sNotificationService.Notify(PORT_REMOVED, id);
return B_OK;
}
+49 -1
View File
@@ -29,6 +29,7 @@
#include <kimage.h>
#include <kscheduler.h>
#include <ksignal.h>
#include <Notifications.h>
#include <port.h>
#include <posix/realtime_sem.h>
#include <posix/xsi_semaphore.h>
@@ -81,6 +82,17 @@ struct fork_arg {
struct arch_fork_arg arch_info;
};
class TeamNotificationService : public DefaultNotificationService {
public:
TeamNotificationService();
void Notify(uint32 opcode, team_id team);
protected:
virtual status_t _ToFlags(const KMessage& eventSpecifier,
uint32& flags);
};
static hash_table *sTeamHash = NULL;
static hash_table *sGroupHash = NULL;
@@ -91,6 +103,8 @@ static struct team *sKernelTeam = NULL;
static int32 sMaxTeams = 2048;
static int32 sUsedTeams = 1;
static TeamNotificationService sNotificationService;
spinlock gTeamSpinlock = B_SPINLOCK_INITIALIZER;
@@ -288,6 +302,35 @@ private:
#endif
// #pragma mark - TeamNotificationService
TeamNotificationService::TeamNotificationService()
: DefaultNotificationService("teams")
{
}
void
TeamNotificationService::Notify(uint32 opcode, team_id team)
{
char eventBuffer[64];
KMessage event;
event.SetTo(eventBuffer, sizeof(eventBuffer), TEAM_MONITOR);
event.AddInt32("opcode", opcode);
event.AddInt32("team", team);
DefaultNotificationService::Notify(event, ~0U);
}
status_t
TeamNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
flags = ~0U;
return B_OK;
}
// #pragma mark - Private functions
@@ -2020,7 +2063,10 @@ team_init(kernel_args *args)
add_debugger_command_etc("teams", &dump_teams, "List all teams",
"\n"
"Prints a list of all existing teams.\n", 0);
return 0;
new(&sNotificationService) TeamNotificationService();
return B_OK;
}
@@ -2374,6 +2420,8 @@ team_delete_team(struct team *team)
}
}
sNotificationService.Notify(TEAM_REMOVED, team->id);
// free team resources
vfs_put_io_context(team->io_context);