* 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:
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -29,124 +29,213 @@
|
|||||||
class NotificationService;
|
class NotificationService;
|
||||||
|
|
||||||
class NotificationListener {
|
class NotificationListener {
|
||||||
public:
|
public:
|
||||||
virtual ~NotificationListener();
|
virtual ~NotificationListener();
|
||||||
|
|
||||||
virtual void EventOccured(NotificationService& service,
|
virtual void EventOccured(NotificationService& service,
|
||||||
const KMessage* event);
|
const KMessage* event);
|
||||||
virtual void AllListenersNotified(NotificationService& service);
|
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
|
bool operator!=(
|
||||||
{ return !(*this == other); }
|
const NotificationListener& other) const
|
||||||
|
{ return !(*this == other); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class UserMessagingMessageSender {
|
class UserMessagingMessageSender {
|
||||||
public:
|
public:
|
||||||
UserMessagingMessageSender();
|
UserMessagingMessageSender();
|
||||||
|
|
||||||
void SendMessage(const KMessage* message, port_id port, int32 token);
|
void SendMessage(const KMessage* message,
|
||||||
void FlushMessage();
|
port_id port, int32 token);
|
||||||
|
void FlushMessage();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum {
|
enum {
|
||||||
MAX_MESSAGING_TARGET_COUNT = 16,
|
MAX_MESSAGING_TARGET_COUNT = 16,
|
||||||
};
|
};
|
||||||
|
|
||||||
const KMessage* fMessage;
|
const KMessage* fMessage;
|
||||||
messaging_target fTargets[MAX_MESSAGING_TARGET_COUNT];
|
messaging_target fTargets[MAX_MESSAGING_TARGET_COUNT];
|
||||||
int32 fTargetCount;
|
int32 fTargetCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UserMessagingListener : public NotificationListener {
|
class UserMessagingListener : public NotificationListener {
|
||||||
public:
|
public:
|
||||||
UserMessagingListener(UserMessagingMessageSender& sender, port_id port,
|
UserMessagingListener(
|
||||||
int32 token);
|
UserMessagingMessageSender& sender,
|
||||||
virtual ~UserMessagingListener();
|
port_id port, int32 token);
|
||||||
|
virtual ~UserMessagingListener();
|
||||||
|
|
||||||
virtual void EventOccured(NotificationService& service,
|
virtual void EventOccured(NotificationService& service,
|
||||||
const KMessage* event);
|
const KMessage* event);
|
||||||
virtual void AllListenersNotified(NotificationService& service);
|
virtual void AllListenersNotified(
|
||||||
|
NotificationService& service);
|
||||||
|
|
||||||
port_id Port() const { return fPort; }
|
port_id Port() const { return fPort; }
|
||||||
int32 Token() const { return fToken; }
|
int32 Token() const { return fToken; }
|
||||||
|
|
||||||
private:
|
bool operator==(
|
||||||
UserMessagingMessageSender& fSender;
|
const NotificationListener& _other) const;
|
||||||
port_id fPort;
|
|
||||||
int32 fToken;
|
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 {
|
class NotificationService : public Referenceable {
|
||||||
public:
|
public:
|
||||||
virtual ~NotificationService();
|
virtual ~NotificationService();
|
||||||
|
|
||||||
virtual status_t AddListener(const KMessage* eventSpecifier,
|
virtual status_t AddListener(const KMessage* eventSpecifier,
|
||||||
NotificationListener& listener) = 0;
|
NotificationListener& listener) = 0;
|
||||||
virtual status_t RemoveListener(const KMessage* eventSpecifier,
|
virtual status_t RemoveListener(const KMessage* eventSpecifier,
|
||||||
NotificationListener& listener) = 0;
|
NotificationListener& listener) = 0;
|
||||||
virtual status_t UpdateListener(const KMessage* eventSpecifier,
|
virtual status_t UpdateListener(const KMessage* eventSpecifier,
|
||||||
NotificationListener& listener) = 0;
|
NotificationListener& listener) = 0;
|
||||||
|
|
||||||
virtual const char* Name() = 0;
|
virtual const char* Name() = 0;
|
||||||
HashTableLink<NotificationService>& Link() { return fLink; }
|
HashTableLink<NotificationService>&
|
||||||
|
Link() { return fLink; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HashTableLink<NotificationService> fLink;
|
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 {
|
class NotificationManager {
|
||||||
public:
|
public:
|
||||||
static NotificationManager& Manager();
|
static NotificationManager& Manager();
|
||||||
static status_t CreateManager();
|
static status_t CreateManager();
|
||||||
|
|
||||||
status_t RegisterService(NotificationService& service);
|
status_t RegisterService(NotificationService& service);
|
||||||
void UnregisterService(NotificationService& service);
|
void UnregisterService(
|
||||||
|
NotificationService& service);
|
||||||
|
|
||||||
NotificationService* GetService(const char* name);
|
status_t AddListener(const char* service,
|
||||||
void PutService(NotificationService* service);
|
uint32 eventMask,
|
||||||
|
NotificationListener& listener);
|
||||||
|
status_t AddListener(const char* service,
|
||||||
|
const KMessage* eventSpecifier,
|
||||||
|
NotificationListener& listener);
|
||||||
|
|
||||||
status_t AddListener(const char* service, uint32 eventMask,
|
status_t UpdateListener(const char* service,
|
||||||
NotificationListener& listener);
|
uint32 eventMask,
|
||||||
status_t AddListener(const char* service,
|
NotificationListener& listener);
|
||||||
const KMessage* eventSpecifier, NotificationListener& listener);
|
status_t UpdateListener(const char* service,
|
||||||
|
const KMessage* eventSpecifier,
|
||||||
|
NotificationListener& listener);
|
||||||
|
|
||||||
status_t UpdateListener(const char* service,
|
status_t RemoveListener(const char* service,
|
||||||
uint32 eventMask, NotificationListener& listener);
|
const KMessage* eventSpecifier,
|
||||||
status_t UpdateListener(const char* service,
|
NotificationListener& listener);
|
||||||
const KMessage* eventSpecifier, NotificationListener& listener);
|
|
||||||
|
|
||||||
status_t RemoveListener(const char* service,
|
private:
|
||||||
const KMessage* eventSpecifier, NotificationListener& listener);
|
NotificationManager();
|
||||||
|
~NotificationManager();
|
||||||
|
|
||||||
private:
|
status_t _Init();
|
||||||
NotificationManager();
|
NotificationService* _ServiceFor(const char* name);
|
||||||
~NotificationManager();
|
|
||||||
|
|
||||||
status_t _Init();
|
struct HashDefinition {
|
||||||
NotificationService* _ServiceFor(const char* name);
|
typedef const char* KeyType;
|
||||||
|
typedef NotificationService ValueType;
|
||||||
|
|
||||||
struct HashDefinition {
|
size_t HashKey(const char* key) const
|
||||||
typedef const char* KeyType;
|
{ return hash_hash_string(key); }
|
||||||
typedef NotificationService ValueType;
|
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
|
static NotificationManager sManager;
|
||||||
{ 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;
|
mutex fLock;
|
||||||
|
ServiceHash fServiceHash;
|
||||||
mutex fLock;
|
|
||||||
typedef OpenHashTable<HashDefinition> ServiceHash;
|
|
||||||
ServiceHash fServiceHash;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT license.
|
||||||
*/
|
*/
|
||||||
#ifndef _KERNEL_PORT_H
|
#ifndef _KERNEL_PORT_H
|
||||||
@@ -22,6 +22,10 @@ enum {
|
|||||||
// kernel-only; memory must be locked
|
// kernel-only; memory must be locked
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// port notifications
|
||||||
|
#define PORT_MONITOR '_Pm_'
|
||||||
|
#define PORT_ADDED 1
|
||||||
|
#define PORT_REMOVED 2
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef _TEAM_H
|
#ifndef _TEAM_H
|
||||||
@@ -9,6 +9,12 @@
|
|||||||
#include <thread_types.h>
|
#include <thread_types.h>
|
||||||
|
|
||||||
|
|
||||||
|
// Team notifications
|
||||||
|
#define TEAM_MONITOR '_Tm_'
|
||||||
|
#define TEAM_ADDED 1
|
||||||
|
#define TEAM_REMOVED 2
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -18,95 +18,38 @@
|
|||||||
# define TRACE(x...) ;
|
# define TRACE(x...) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: add possibility to remove teams/ports that are gone
|
|
||||||
|
|
||||||
|
class NetNotificationService : public DefaultUserNotificationService {
|
||||||
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 {
|
|
||||||
public:
|
public:
|
||||||
NetNotificationService();
|
NetNotificationService();
|
||||||
virtual ~NetNotificationService();
|
virtual ~NetNotificationService();
|
||||||
|
|
||||||
void Notify(const KMessage& event);
|
void Notify(const KMessage& event);
|
||||||
|
|
||||||
status_t AddListener(const KMessage* eventSpecifier,
|
protected:
|
||||||
NotificationListener& listener);
|
virtual status_t _ToFlags(const KMessage& eventSpecifier,
|
||||||
status_t UpdateListener(const KMessage* eventSpecifier,
|
uint32& flags);
|
||||||
NotificationListener& listener);
|
virtual void _FirstAdded();
|
||||||
status_t RemoveListener(const KMessage* eventSpecifier,
|
virtual void _LastRemoved();
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static NetNotificationService sNotificationService;
|
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
|
// #pragma mark - NetNotificationService
|
||||||
|
|
||||||
|
|
||||||
NetNotificationService::NetNotificationService()
|
NetNotificationService::NetNotificationService()
|
||||||
|
: DefaultUserNotificationService("network")
|
||||||
{
|
{
|
||||||
recursive_lock_init(&fRecursiveLock, "net notifications");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NetNotificationService::~NetNotificationService()
|
NetNotificationService::~NetNotificationService()
|
||||||
{
|
{
|
||||||
recursive_lock_destroy(&fRecursiveLock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Notifies all registered listeners.
|
|
||||||
\param event The message defining the event
|
|
||||||
*/
|
|
||||||
void
|
void
|
||||||
NetNotificationService::Notify(const KMessage& event)
|
NetNotificationService::Notify(const KMessage& event)
|
||||||
{
|
{
|
||||||
@@ -116,173 +59,36 @@ NetNotificationService::Notify(const KMessage& event)
|
|||||||
|
|
||||||
TRACE("notify for %lx\n", opcode);
|
TRACE("notify for %lx\n", opcode);
|
||||||
|
|
||||||
RecursiveLocker _(fRecursiveLock);
|
DefaultUserNotificationService::Notify(event, opcode);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
NetNotificationService::AddListener(const KMessage* eventSpecifier,
|
NetNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
|
||||||
NotificationListener& listener)
|
|
||||||
{
|
{
|
||||||
if (eventSpecifier == NULL)
|
flags = eventSpecifier.GetInt32("flags", 0);
|
||||||
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 == ¬ificationListener) {
|
|
||||||
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*>(¬ificationListener) != NULL
|
|
||||||
? "user " : "", listener, flags);
|
|
||||||
|
|
||||||
listener->flags = flags;
|
|
||||||
listener->listener = ¬ificationListener;
|
|
||||||
|
|
||||||
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);
|
|
||||||
return B_OK;
|
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
|
// #pragma mark - User generic syscall
|
||||||
|
|
||||||
|
|
||||||
@@ -326,7 +132,6 @@ notifications_std_ops(int32 op, ...)
|
|||||||
case B_MODULE_INIT:
|
case B_MODULE_INIT:
|
||||||
TRACE("init\n");
|
TRACE("init\n");
|
||||||
|
|
||||||
new(&sNotificationSender) UserMessagingMessageSender();
|
|
||||||
new(&sNotificationService) NetNotificationService();
|
new(&sNotificationService) NetNotificationService();
|
||||||
|
|
||||||
register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
|
register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS,
|
||||||
@@ -338,7 +143,6 @@ notifications_std_ops(int32 op, ...)
|
|||||||
|
|
||||||
unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
|
unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1);
|
||||||
|
|
||||||
sNotificationSender.~UserMessagingMessageSender();
|
|
||||||
sNotificationService.~NetNotificationService();
|
sNotificationService.~NetNotificationService();
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@@ -10,11 +10,13 @@
|
|||||||
|
|
||||||
#include <Notifications.h>
|
#include <Notifications.h>
|
||||||
|
|
||||||
|
#include <team.h>
|
||||||
|
|
||||||
|
|
||||||
NotificationManager NotificationManager::sManager;
|
NotificationManager NotificationManager::sManager;
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - UserMessagingListener
|
// #pragma mark - NotificationListener
|
||||||
|
|
||||||
|
|
||||||
NotificationListener::~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 = ¬ificationListener;
|
||||||
|
|
||||||
|
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 == ¬ificationListener) {
|
||||||
|
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 == ¬ificationListener) {
|
||||||
|
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 = ¬ificationListener;
|
||||||
|
|
||||||
|
RecursiveLocker _(fLock);
|
||||||
|
if (fListeners.IsEmpty())
|
||||||
|
_FirstAdded();
|
||||||
|
fListeners.Add(listener);
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - NotificationManager
|
// #pragma mark - NotificationManager
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -130,6 +130,8 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
|||||||
boot_item_init();
|
boot_item_init();
|
||||||
driver_settings_init(&sKernelArgs);
|
driver_settings_init(&sKernelArgs);
|
||||||
debug_init_post_vm(&sKernelArgs);
|
debug_init_post_vm(&sKernelArgs);
|
||||||
|
TRACE("init notification services\n");
|
||||||
|
notifications_init();
|
||||||
TRACE("init teams\n");
|
TRACE("init teams\n");
|
||||||
team_init(&sKernelArgs);
|
team_init(&sKernelArgs);
|
||||||
TRACE("init ELF loader\n");
|
TRACE("init ELF loader\n");
|
||||||
@@ -180,8 +182,6 @@ _start(kernel_args *bootKernelArgs, int currentCPU)
|
|||||||
TRACE("init VM threads\n");
|
TRACE("init VM threads\n");
|
||||||
vm_init_post_thread(&sKernelArgs);
|
vm_init_post_thread(&sKernelArgs);
|
||||||
low_resource_manager_init_post_thread();
|
low_resource_manager_init_post_thread();
|
||||||
TRACE("init notification services\n");
|
|
||||||
notifications_init();
|
|
||||||
TRACE("init VFS\n");
|
TRACE("init VFS\n");
|
||||||
vfs_init(&sKernelArgs);
|
vfs_init(&sKernelArgs);
|
||||||
#if ENABLE_SWAP_SUPPORT
|
#if ENABLE_SWAP_SUPPORT
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2007, Axel Dörfler, [email protected].
|
* Copyright 2002-2009, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001, Mark-Jan Bastian. All rights reserved.
|
* Copyright 2001, Mark-Jan Bastian. All rights reserved.
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <arch/int.h>
|
#include <arch/int.h>
|
||||||
#include <cbuf.h>
|
#include <cbuf.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include <Notifications.h>
|
||||||
#include <sem.h>
|
#include <sem.h>
|
||||||
#include <syscall_restart.h>
|
#include <syscall_restart.h>
|
||||||
#include <team.h>
|
#include <team.h>
|
||||||
@@ -59,6 +60,16 @@ struct port_entry {
|
|||||||
struct list msg_queue;
|
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 MAX_QUEUE_LENGTH 4096
|
||||||
#define PORT_MAX_MESSAGE_SIZE (256 * 1024)
|
#define PORT_MAX_MESSAGE_SIZE (256 * 1024)
|
||||||
@@ -73,6 +84,8 @@ static bool sPortsActive = false;
|
|||||||
static port_id sNextPort = 1;
|
static port_id sNextPort = 1;
|
||||||
static int32 sFirstFreeSlot = 1;
|
static int32 sFirstFreeSlot = 1;
|
||||||
|
|
||||||
|
static PortNotificationService sNotificationService;
|
||||||
|
|
||||||
static spinlock sPortSpinlock = B_SPINLOCK_INITIALIZER;
|
static spinlock sPortSpinlock = B_SPINLOCK_INITIALIZER;
|
||||||
|
|
||||||
#define GRAB_PORT_LIST_LOCK() acquire_spinlock(&sPortSpinlock)
|
#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)
|
#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
|
static int
|
||||||
dump_port_list(int argc, char **argv)
|
dump_port_list(int argc, char **argv)
|
||||||
{
|
{
|
||||||
@@ -362,6 +408,7 @@ port_init(kernel_args *args)
|
|||||||
" <name> - Name of the port.\n"
|
" <name> - Name of the port.\n"
|
||||||
" <sem> - ID of the port's read or write semaphore.\n", 0);
|
" <sem> - ID of the port's read or write semaphore.\n", 0);
|
||||||
|
|
||||||
|
new(&sNotificationService) PortNotificationService();
|
||||||
sPortsActive = true;
|
sPortsActive = true;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
@@ -380,7 +427,8 @@ create_port(int32 queueLength, const char *name)
|
|||||||
team_id owner;
|
team_id owner;
|
||||||
int32 slot;
|
int32 slot;
|
||||||
|
|
||||||
TRACE(("create_port(queueLength = %ld, name = \"%s\")\n", queueLength, name));
|
TRACE(("create_port(queueLength = %ld, name = \"%s\")\n", queueLength,
|
||||||
|
name));
|
||||||
|
|
||||||
if (!sPortsActive)
|
if (!sPortsActive)
|
||||||
return B_BAD_PORT_ID;
|
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));
|
TRACE(("create_port() done: port created %ld\n", id));
|
||||||
|
|
||||||
|
sNotificationService.Notify(PORT_ADDED, id);
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// not enough ports...
|
// 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
|
// long as sMaxPorts stays constant over the kernel run
|
||||||
// time (which it should be). IOW we could simply panic()
|
// time (which it should be). IOW we could simply panic()
|
||||||
// here.
|
// 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
|
// read_port() will see the B_BAD_SEM_ID acq_sem() return value, and act accordingly
|
||||||
delete_sem(readSem);
|
delete_sem(readSem);
|
||||||
delete_sem(writeSem);
|
delete_sem(writeSem);
|
||||||
|
sNotificationService.Notify(PORT_REMOVED, id);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <kimage.h>
|
#include <kimage.h>
|
||||||
#include <kscheduler.h>
|
#include <kscheduler.h>
|
||||||
#include <ksignal.h>
|
#include <ksignal.h>
|
||||||
|
#include <Notifications.h>
|
||||||
#include <port.h>
|
#include <port.h>
|
||||||
#include <posix/realtime_sem.h>
|
#include <posix/realtime_sem.h>
|
||||||
#include <posix/xsi_semaphore.h>
|
#include <posix/xsi_semaphore.h>
|
||||||
@@ -81,6 +82,17 @@ struct fork_arg {
|
|||||||
struct arch_fork_arg arch_info;
|
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 *sTeamHash = NULL;
|
||||||
static hash_table *sGroupHash = NULL;
|
static hash_table *sGroupHash = NULL;
|
||||||
@@ -91,6 +103,8 @@ static struct team *sKernelTeam = NULL;
|
|||||||
static int32 sMaxTeams = 2048;
|
static int32 sMaxTeams = 2048;
|
||||||
static int32 sUsedTeams = 1;
|
static int32 sUsedTeams = 1;
|
||||||
|
|
||||||
|
static TeamNotificationService sNotificationService;
|
||||||
|
|
||||||
spinlock gTeamSpinlock = B_SPINLOCK_INITIALIZER;
|
spinlock gTeamSpinlock = B_SPINLOCK_INITIALIZER;
|
||||||
|
|
||||||
|
|
||||||
@@ -288,6 +302,35 @@ private:
|
|||||||
#endif
|
#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
|
// #pragma mark - Private functions
|
||||||
|
|
||||||
@@ -2020,7 +2063,10 @@ team_init(kernel_args *args)
|
|||||||
add_debugger_command_etc("teams", &dump_teams, "List all teams",
|
add_debugger_command_etc("teams", &dump_teams, "List all teams",
|
||||||
"\n"
|
"\n"
|
||||||
"Prints a list of all existing teams.\n", 0);
|
"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
|
// free team resources
|
||||||
|
|
||||||
vfs_put_io_context(team->io_context);
|
vfs_put_io_context(team->io_context);
|
||||||
|
|||||||
Reference in New Issue
Block a user