* Cleared up a misconception in the notification mechanism. We already had

methods that used an "event mask" field. There was no need to introduce
  a "flags" field for the same purpose.
* Renamed protected DefaultNotificationService methods (removed "_" prefix).
* Adjusted the code providing a notification service accordingly.
* Changed the event message several notification services generated by renaming
  the "opcode" field to "event".
* Implemented the TEAM_ADDED event and also added a TEAM_EXEC event.
* Added notifications for threads and images.
* Added visitor-like iteration functions for teams, threads, and images.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@30126 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-04-11 21:45:25 +00:00
parent 78c00a4a53
commit efd536ff89
12 changed files with 242 additions and 113 deletions
+8 -8
View File
@@ -118,7 +118,7 @@ private:
struct default_listener : public DoublyLinkedListLinkImpl<default_listener> { struct default_listener : public DoublyLinkedListLinkImpl<default_listener> {
~default_listener(); ~default_listener();
uint32 flags; uint32 eventMask;
team_id team; team_id team;
NotificationListener* listener; NotificationListener* listener;
}; };
@@ -131,7 +131,7 @@ public:
DefaultNotificationService(const char* name); DefaultNotificationService(const char* name);
virtual ~DefaultNotificationService(); virtual ~DefaultNotificationService();
void Notify(const KMessage& event, uint32 flags); void Notify(const KMessage& event, uint32 eventMask);
virtual status_t AddListener(const KMessage* eventSpecifier, virtual status_t AddListener(const KMessage* eventSpecifier,
NotificationListener& listener); NotificationListener& listener);
@@ -143,10 +143,10 @@ public:
virtual const char* Name() { return fName; } virtual const char* Name() { return fName; }
protected: protected:
virtual status_t _ToFlags(const KMessage& eventSpecifier, virtual status_t ToEventMask(const KMessage& eventSpecifier,
uint32& flags); uint32& eventMask);
virtual void _FirstAdded(); virtual void FirstAdded();
virtual void _LastRemoved(); virtual void LastRemoved();
recursive_lock fLock; recursive_lock fLock;
DefaultListenerList fListeners; DefaultListenerList fListeners;
@@ -168,7 +168,7 @@ public:
NotificationListener& listener); NotificationListener& listener);
status_t RemoveUserListeners(port_id port, uint32 token); status_t RemoveUserListeners(port_id port, uint32 token);
status_t UpdateUserListener(uint32 flags, status_t UpdateUserListener(uint32 eventMask,
port_id port, uint32 token); port_id port, uint32 token);
private: private:
@@ -176,7 +176,7 @@ private:
const KMessage* event); const KMessage* event);
virtual void AllListenersNotified( virtual void AllListenersNotified(
NotificationService& service); NotificationService& service);
status_t _AddListener(uint32 flags, status_t _AddListener(uint32 eventMask,
NotificationListener& listener); NotificationListener& listener);
UserMessagingMessageSender fSender; UserMessagingMessageSender fSender;
+25 -1
View File
@@ -5,12 +5,32 @@
#ifndef _KERNEL_IMAGE_H #ifndef _KERNEL_IMAGE_H
#define _KERNEL_IMAGE_H #define _KERNEL_IMAGE_H
#include <image.h> #include <image.h>
struct image;
struct team; struct team;
#ifdef __cplusplus
#include <util/OpenHashTable.h>
struct image {
struct image* next;
struct image* prev;
HashTableLink<image> hash_link;
image_info info;
team_id team;
};
#endif // __cplusplus
// image notifications
#define IMAGE_MONITOR '_Im_'
#define IMAGE_ADDED 0x01
#define IMAGE_REMOVED 0x02
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -20,6 +40,10 @@ extern status_t unregister_image(struct team *team, image_id id);
extern int32 count_images(struct team *team); extern int32 count_images(struct team *team);
extern status_t remove_images(struct team *team); extern status_t remove_images(struct team *team);
typedef bool (*image_iterator_callback)(struct image* image, void* cookie);
struct image* image_iterate_through_images(image_iterator_callback callback,
void* cookie);
extern status_t image_debug_lookup_user_symbol_address(struct team *team, extern status_t image_debug_lookup_user_symbol_address(struct team *team,
addr_t address, addr_t *_baseAddress, const char **_symbolName, addr_t address, addr_t *_baseAddress, const char **_symbolName,
const char **_imageName, bool *_exactMatch); const char **_imageName, bool *_exactMatch);
+2 -2
View File
@@ -24,8 +24,8 @@ enum {
// port notifications // port notifications
#define PORT_MONITOR '_Pm_' #define PORT_MONITOR '_Pm_'
#define PORT_ADDED 1 #define PORT_ADDED 0x01
#define PORT_REMOVED 2 #define PORT_REMOVED 0x02
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
+8 -3
View File
@@ -9,10 +9,11 @@
#include <thread_types.h> #include <thread_types.h>
// Team notifications // team notifications
#define TEAM_MONITOR '_Tm_' #define TEAM_MONITOR '_Tm_'
#define TEAM_ADDED 1 #define TEAM_ADDED 0x01
#define TEAM_REMOVED 2 #define TEAM_REMOVED 0x02
#define TEAM_EXEC 0x04
#ifdef __cplusplus #ifdef __cplusplus
@@ -40,6 +41,10 @@ struct team *team_get_team_struct_locked(team_id id);
int32 team_max_teams(void); int32 team_max_teams(void);
int32 team_used_teams(void); int32 team_used_teams(void);
typedef bool (*team_iterator_callback)(struct team* team, void* cookie);
struct team* team_iterate_through_teams(team_iterator_callback callback,
void* cookie);
thread_id load_image_etc(int32 argCount, const char* const* args, thread_id load_image_etc(int32 argCount, const char* const* args,
const char* const* env, int32 priority, team_id parentID, uint32 flags); const char* const* env, int32 priority, team_id parentID, uint32 flags);
+10
View File
@@ -23,6 +23,12 @@ struct select_info;
struct thread_creation_attributes; struct thread_creation_attributes;
// thread notifications
#define THREAD_MONITOR '_tm_'
#define THREAD_ADDED 0x01
#define THREAD_REMOVED 0x02
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@@ -70,6 +76,10 @@ thread_is_idle_thread(struct thread *thread)
return thread->entry == NULL; return thread->entry == NULL;
} }
typedef bool (*thread_iterator_callback)(struct thread* thread, void* cookie);
struct thread* thread_iterate_through_threads(thread_iterator_callback callback,
void* cookie);
thread_id allocate_thread_id(void); thread_id allocate_thread_id(void);
thread_id peek_next_thread_id(void); thread_id peek_next_thread_id(void);
@@ -27,10 +27,8 @@ public:
void Notify(const KMessage& event); void Notify(const KMessage& event);
protected: protected:
virtual status_t _ToFlags(const KMessage& eventSpecifier, virtual void FirstAdded();
uint32& flags); virtual void LastRemoved();
virtual void _FirstAdded();
virtual void _LastRemoved();
}; };
static NetNotificationService sNotificationService; static NetNotificationService sNotificationService;
@@ -63,16 +61,8 @@ NetNotificationService::Notify(const KMessage& event)
} }
status_t
NetNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
flags = eventSpecifier.GetInt32("flags", 0);
return B_OK;
}
void void
NetNotificationService::_FirstAdded() NetNotificationService::FirstAdded()
{ {
// The reference counting doesn't work for us, as we'll have to // The reference counting doesn't work for us, as we'll have to
// ensure our module stays loaded. // ensure our module stays loaded.
@@ -82,7 +72,7 @@ NetNotificationService::_FirstAdded()
void void
NetNotificationService::_LastRemoved() NetNotificationService::LastRemoved()
{ {
// Give up the reference _AddListener() // Give up the reference _AddListener()
put_module(NET_NOTIFICATIONS_MODULE_NAME); put_module(NET_NOTIFICATIONS_MODULE_NAME);
+45 -36
View File
@@ -13,6 +13,9 @@
#include <team.h> #include <team.h>
static const char* kEventMaskString = "event mask";
NotificationManager NotificationManager::sManager; NotificationManager NotificationManager::sManager;
@@ -158,22 +161,28 @@ DefaultNotificationService::~DefaultNotificationService()
/*! \brief Notifies all registered listeners. /*! \brief Notifies all registered listeners.
\param event The message defining the event \param event The message defining the event
\param flags The flags that must be set in listeners to receive this event \param eventMask Only listeners with an event mask sharing at least one
common bit with this mask will receive the event.
*/ */
void void
DefaultNotificationService::Notify(const KMessage& event, uint32 flags) DefaultNotificationService::Notify(const KMessage& event, uint32 eventMask)
{ {
RecursiveLocker _(fLock); RecursiveLocker _(fLock);
// Note: The following iterations support that the listener removes itself
// in the hook method. That's a property of the DoublyLinkedList iterator.
// notify all listeners about the event
DefaultListenerList::Iterator iterator = fListeners.GetIterator(); DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) { while (default_listener* listener = iterator.Next()) {
if ((flags & listener->flags) != 0) if ((eventMask & listener->eventMask) != 0)
listener->listener->EventOccured(*this, &event); listener->listener->EventOccured(*this, &event);
} }
// notify all listeners that all listeners have been notified
iterator = fListeners.GetIterator(); iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) { while (default_listener* listener = iterator.Next()) {
if ((flags & listener->flags) != 0) if ((eventMask & listener->eventMask) != 0)
listener->listener->AllListenersNotified(*this); listener->listener->AllListenersNotified(*this);
} }
} }
@@ -186,8 +195,8 @@ DefaultNotificationService::AddListener(const KMessage* eventSpecifier,
if (eventSpecifier == NULL) if (eventSpecifier == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
uint32 flags; uint32 eventMask;
status_t status = _ToFlags(*eventSpecifier, flags); status_t status = ToEventMask(*eventSpecifier, eventMask);
if (status != B_OK) if (status != B_OK)
return status; return status;
@@ -195,13 +204,13 @@ DefaultNotificationService::AddListener(const KMessage* eventSpecifier,
if (listener == NULL) if (listener == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
listener->flags = flags; listener->eventMask = eventMask;
listener->team = -1; listener->team = -1;
listener->listener = &notificationListener; listener->listener = &notificationListener;
RecursiveLocker _(fLock); RecursiveLocker _(fLock);
if (fListeners.IsEmpty()) if (fListeners.IsEmpty())
_FirstAdded(); FirstAdded();
fListeners.Add(listener); fListeners.Add(listener);
return B_OK; return B_OK;
@@ -227,9 +236,9 @@ DefaultNotificationService::RemoveListener(const KMessage* eventSpecifier,
if (listener->listener == &notificationListener) { if (listener->listener == &notificationListener) {
iterator.Remove(); iterator.Remove();
delete listener; delete listener;
if (fListeners.IsEmpty()) if (fListeners.IsEmpty())
_LastRemoved(); LastRemoved();
return B_OK; return B_OK;
} }
} }
@@ -239,21 +248,21 @@ DefaultNotificationService::RemoveListener(const KMessage* eventSpecifier,
status_t status_t
DefaultNotificationService::_ToFlags(const KMessage& eventSpecifier, DefaultNotificationService::ToEventMask(const KMessage& eventSpecifier,
uint32& flags) uint32& eventMask)
{ {
return eventSpecifier.FindInt32("flags", (int32*)&flags); return eventSpecifier.FindInt32("event mask", (int32*)&eventMask);
} }
void void
DefaultNotificationService::_FirstAdded() DefaultNotificationService::FirstAdded()
{ {
} }
void void
DefaultNotificationService::_LastRemoved() DefaultNotificationService::LastRemoved()
{ {
} }
@@ -281,9 +290,9 @@ DefaultUserNotificationService::AddListener(const KMessage* eventSpecifier,
if (eventSpecifier == NULL) if (eventSpecifier == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
uint32 flags = eventSpecifier->GetInt32("flags", 0); uint32 eventMask = eventSpecifier->GetInt32(kEventMaskString, 0);
return _AddListener(flags, listener); return _AddListener(eventMask, listener);
} }
@@ -294,18 +303,18 @@ DefaultUserNotificationService::UpdateListener(const KMessage* eventSpecifier,
if (eventSpecifier == NULL) if (eventSpecifier == NULL)
return B_BAD_VALUE; return B_BAD_VALUE;
uint32 flags = eventSpecifier->GetInt32("flags", 0); uint32 eventMask = eventSpecifier->GetInt32(kEventMaskString, 0);
bool addFlags = eventSpecifier->GetBool("add flags", false); bool addEvents = eventSpecifier->GetBool("add events", false);
RecursiveLocker _(fLock); RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator(); DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) { while (default_listener* listener = iterator.Next()) {
if (*listener->listener == notificationListener) { if (*listener->listener == notificationListener) {
if (addFlags) if (addEvents)
listener->flags |= flags; listener->eventMask |= eventMask;
else else
listener->flags = flags; listener->eventMask = eventMask;
return B_OK; return B_OK;
} }
} }
@@ -345,9 +354,9 @@ DefaultUserNotificationService::RemoveUserListeners(port_id port, uint32 token)
if (*listener->listener == userListener) { if (*listener->listener == userListener) {
iterator.Remove(); iterator.Remove();
delete listener; delete listener;
if (fListeners.IsEmpty()) if (fListeners.IsEmpty())
_LastRemoved(); LastRemoved();
return B_OK; return B_OK;
} }
} }
@@ -357,8 +366,8 @@ DefaultUserNotificationService::RemoveUserListeners(port_id port, uint32 token)
status_t status_t
DefaultUserNotificationService::UpdateUserListener(uint32 flags, port_id port, DefaultUserNotificationService::UpdateUserListener(uint32 eventMask,
uint32 token) port_id port, uint32 token)
{ {
UserMessagingListener userListener(fSender, port, token); UserMessagingListener userListener(fSender, port, token);
@@ -367,7 +376,7 @@ DefaultUserNotificationService::UpdateUserListener(uint32 flags, port_id port,
DefaultListenerList::Iterator iterator = fListeners.GetIterator(); DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) { while (default_listener* listener = iterator.Next()) {
if (*listener->listener == userListener) { if (*listener->listener == userListener) {
listener->flags |= flags; listener->eventMask |= eventMask;
return B_OK; return B_OK;
} }
} }
@@ -377,7 +386,7 @@ DefaultUserNotificationService::UpdateUserListener(uint32 flags, port_id port,
if (copiedListener == NULL) if (copiedListener == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
status_t status = _AddListener(flags, *copiedListener); status_t status = _AddListener(eventMask, *copiedListener);
if (status != B_OK) if (status != B_OK)
delete copiedListener; delete copiedListener;
@@ -389,13 +398,13 @@ void
DefaultUserNotificationService::EventOccured(NotificationService& service, DefaultUserNotificationService::EventOccured(NotificationService& service,
const KMessage* event) const KMessage* event)
{ {
int32 opcode = event->GetInt32("opcode", -1); int32 eventCode = event->GetInt32("event", -1);
team_id team = event->GetInt32("team", -1); team_id team = event->GetInt32("team", -1);
if (opcode == TEAM_REMOVED && team >= B_OK) { if (eventCode == TEAM_REMOVED && team >= B_OK) {
// check if we have any listeners from that team, and remove them // check if we have any listeners from that team, and remove them
RecursiveLocker _(fLock); RecursiveLocker _(fLock);
DefaultListenerList::Iterator iterator = fListeners.GetIterator(); DefaultListenerList::Iterator iterator = fListeners.GetIterator();
while (default_listener* listener = iterator.Next()) { while (default_listener* listener = iterator.Next()) {
if (listener->team == team) { if (listener->team == team) {
@@ -415,20 +424,20 @@ DefaultUserNotificationService::AllListenersNotified(
status_t status_t
DefaultUserNotificationService::_AddListener(uint32 flags, DefaultUserNotificationService::_AddListener(uint32 eventMask,
NotificationListener& notificationListener) NotificationListener& notificationListener)
{ {
default_listener* listener = new(std::nothrow) default_listener; default_listener* listener = new(std::nothrow) default_listener;
if (listener == NULL) if (listener == NULL)
return B_NO_MEMORY; return B_NO_MEMORY;
listener->flags = flags; listener->eventMask = eventMask;
listener->team = team_get_current_team_id(); listener->team = team_get_current_team_id();
listener->listener = &notificationListener; listener->listener = &notificationListener;
RecursiveLocker _(fLock); RecursiveLocker _(fLock);
if (fListeners.IsEmpty()) if (fListeners.IsEmpty())
_FirstAdded(); FirstAdded();
fListeners.Add(listener); fListeners.Add(listener);
return B_OK; return B_OK;
@@ -511,7 +520,7 @@ NotificationManager::AddListener(const char* serviceName,
char buffer[96]; char buffer[96];
KMessage specifier; KMessage specifier;
specifier.SetTo(buffer, sizeof(buffer), 0); specifier.SetTo(buffer, sizeof(buffer), 0);
specifier.AddInt32("event mask", eventMask); specifier.AddInt32(kEventMaskString, eventMask);
return AddListener(serviceName, &specifier, listener); return AddListener(serviceName, &specifier, listener);
} }
@@ -540,7 +549,7 @@ NotificationManager::UpdateListener(const char* serviceName,
char buffer[96]; char buffer[96];
KMessage specifier; KMessage specifier;
specifier.SetTo(buffer, sizeof(buffer), 0); specifier.SetTo(buffer, sizeof(buffer), 0);
specifier.AddInt32("event mask", eventMask); specifier.AddInt32(kEventMaskString, eventMask);
return UpdateListener(serviceName, &specifier, listener); return UpdateListener(serviceName, &specifier, listener);
} }
@@ -195,13 +195,6 @@ public:
virtual ~DiskNotifications() virtual ~DiskNotifications()
{ {
} }
protected:
status_t _ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
flags = eventSpecifier.GetInt32("flags", 0);
return B_OK;
}
}; };
+48 -9
View File
@@ -12,11 +12,12 @@
#include <kimage.h> #include <kimage.h>
#include <kscheduler.h> #include <kscheduler.h>
#include <lock.h> #include <lock.h>
#include <Notifications.h>
#include <team.h> #include <team.h>
#include <thread.h> #include <thread.h>
#include <thread_types.h> #include <thread_types.h>
#include <user_debugger.h> #include <user_debugger.h>
#include <util/OpenHashTable.h> #include <util/AutoLock.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -31,14 +32,6 @@
#define ADD_DEBUGGER_COMMANDS #define ADD_DEBUGGER_COMMANDS
struct image {
struct image* next;
struct image* prev;
HashTableLink<image> hash_link;
image_info info;
team_id team;
};
struct ImageTableDefinition { struct ImageTableDefinition {
typedef image_id KeyType; typedef image_id KeyType;
@@ -55,9 +48,31 @@ struct ImageTableDefinition {
typedef OpenHashTable<ImageTableDefinition> ImageTable; typedef OpenHashTable<ImageTableDefinition> ImageTable;
class ImageNotificationService : public DefaultNotificationService {
public:
ImageNotificationService()
: DefaultNotificationService("images")
{
}
void Notify(uint32 eventCode, struct image* image)
{
char eventBuffer[128];
KMessage event;
event.SetTo(eventBuffer, sizeof(eventBuffer), IMAGE_MONITOR);
event.AddInt32("event", eventCode);
event.AddInt32("image", image->info.id);
event.AddPointer("imageStruct", image);
DefaultNotificationService::Notify(event, eventCode);
}
};
static image_id sNextImageID = 1; static image_id sNextImageID = 1;
static mutex sImageMutex = MUTEX_INITIALIZER("image"); static mutex sImageMutex = MUTEX_INITIALIZER("image");
static ImageTable* sImageTable; static ImageTable* sImageTable;
static ImageNotificationService sNotificationService;
/*! Registers an image with the specified team. /*! Registers an image with the specified team.
@@ -87,6 +102,9 @@ register_image(struct team *team, image_info *_info, size_t size)
list_add_item(&team->image_list, image); list_add_item(&team->image_list, image);
sImageTable->Insert(image); sImageTable->Insert(image);
// notify listeners
sNotificationService.Notify(IMAGE_ADDED, image);
mutex_unlock(&sImageMutex); mutex_unlock(&sImageMutex);
TRACE(("register_image(team = %p, image id = %ld, image = %p\n", team, id, image)); TRACE(("register_image(team = %p, image id = %ld, image = %p\n", team, id, image));
@@ -116,6 +134,9 @@ unregister_image(struct team *team, image_id id)
// notify the debugger // notify the debugger
user_debug_image_deleted(&image->info); user_debug_image_deleted(&image->info);
// notify listeners
sNotificationService.Notify(IMAGE_REMOVED, image);
free(image); free(image);
} }
@@ -263,6 +284,22 @@ dump_images_list(int argc, char **argv)
#endif #endif
struct image*
image_iterate_through_images(image_iterator_callback callback, void* cookie)
{
MutexLocker locker(sImageMutex);
ImageTable::Iterator it = sImageTable->GetIterator();
struct image* image = NULL;
while ((image = it.Next()) != NULL) {
if (callback(image, cookie))
break;
}
return image;
}
status_t status_t
image_debug_lookup_user_symbol_address(struct team *team, addr_t address, image_debug_lookup_user_symbol_address(struct team *team, addr_t address,
addr_t *_baseAddress, const char **_symbolName, const char **_imageName, addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
@@ -310,6 +347,8 @@ image_init(void)
return error; return error;
} }
new(&sNotificationService) ImageNotificationService();
#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
+2 -14
View File
@@ -65,10 +65,6 @@ public:
PortNotificationService(); PortNotificationService();
void Notify(uint32 opcode, port_id team); 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
@@ -109,18 +105,10 @@ PortNotificationService::Notify(uint32 opcode, port_id port)
char eventBuffer[64]; char eventBuffer[64];
KMessage event; KMessage event;
event.SetTo(eventBuffer, sizeof(eventBuffer), PORT_MONITOR); event.SetTo(eventBuffer, sizeof(eventBuffer), PORT_MONITOR);
event.AddInt32("opcode", opcode); event.AddInt32("event", opcode);
event.AddInt32("port", port); event.AddInt32("port", port);
DefaultNotificationService::Notify(event, ~0U); DefaultNotificationService::Notify(event, opcode);
}
status_t
PortNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
flags = ~0U;
return B_OK;
} }
+37 -19
View File
@@ -86,11 +86,7 @@ class TeamNotificationService : public DefaultNotificationService {
public: public:
TeamNotificationService(); TeamNotificationService();
void Notify(uint32 opcode, team_id team); void Notify(uint32 eventCode, struct team* team);
protected:
virtual status_t _ToFlags(const KMessage& eventSpecifier,
uint32& flags);
}; };
@@ -312,23 +308,16 @@ TeamNotificationService::TeamNotificationService()
void void
TeamNotificationService::Notify(uint32 opcode, team_id team) TeamNotificationService::Notify(uint32 eventCode, struct team* team)
{ {
char eventBuffer[64]; char eventBuffer[128];
KMessage event; KMessage event;
event.SetTo(eventBuffer, sizeof(eventBuffer), TEAM_MONITOR); event.SetTo(eventBuffer, sizeof(eventBuffer), TEAM_MONITOR);
event.AddInt32("opcode", opcode); event.AddInt32("event", eventCode);
event.AddInt32("team", team); event.AddInt32("team", team->id);
event.AddPointer("teamStruct", team);
DefaultNotificationService::Notify(event, ~0U); DefaultNotificationService::Notify(event, eventCode);
}
status_t
TeamNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
{
flags = ~0U;
return B_OK;
} }
@@ -1236,6 +1225,9 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount,
if (status != B_OK) if (status != B_OK)
goto err4; goto err4;
// notify team listeners
sNotificationService.Notify(TEAM_ADDED, team);
// Create a kernel thread, but under the context of the new team // Create a kernel thread, but under the context of the new team
// The new thread will take over ownership of teamArgs // The new thread will take over ownership of teamArgs
thread = spawn_kernel_thread_etc(team_create_thread_start, threadName, thread = spawn_kernel_thread_etc(team_create_thread_start, threadName,
@@ -1430,6 +1422,9 @@ exec_team(const char *path, char**& _flatArgs, size_t flatArgsSize,
user_debug_team_exec(); user_debug_team_exec();
// notify team listeners
sNotificationService.Notify(TEAM_EXEC, team);
status = team_create_thread_start(teamArgs); status = team_create_thread_start(teamArgs);
// this one usually doesn't return... // this one usually doesn't return...
@@ -1603,6 +1598,9 @@ fork_team(void)
goto err5; goto err5;
} }
// notify team listeners
sNotificationService.Notify(TEAM_ADDED, team);
// create a kernel thread under the context of the new team // create a kernel thread under the context of the new team
threadID = spawn_kernel_thread_etc(fork_team_thread_start, threadID = spawn_kernel_thread_etc(fork_team_thread_start,
parentThread->name, parentThread->priority, forkArgs, parentThread->name, parentThread->priority, forkArgs,
@@ -2084,6 +2082,26 @@ team_used_teams(void)
} }
/*! Iterates through the list of teams. The team spinlock must be held.
*/
struct team*
team_iterate_through_teams(team_iterator_callback callback, void* cookie)
{
struct hash_iterator iterator;
hash_open(sTeamHash, &iterator);
struct team* team;
while ((team = (struct team*)hash_next(sTeamHash, &iterator)) != NULL) {
if (callback(team, cookie))
break;
}
hash_close(sTeamHash, &iterator, false);
return team;
}
/*! Fills the provided death entry if it's in the team. /*! Fills the provided death entry if it's in the team.
You need to have the team lock held when calling this function. You need to have the team lock held when calling this function.
*/ */
@@ -2420,7 +2438,7 @@ team_delete_team(struct team *team)
} }
} }
sNotificationService.Notify(TEAM_REMOVED, team->id); sNotificationService.Notify(TEAM_REMOVED, team);
// free team resources // free team resources
+53
View File
@@ -30,6 +30,7 @@
#include <kimage.h> #include <kimage.h>
#include <kscheduler.h> #include <kscheduler.h>
#include <ksignal.h> #include <ksignal.h>
#include <Notifications.h>
#include <real_time_clock.h> #include <real_time_clock.h>
#include <smp.h> #include <smp.h>
#include <syscalls.h> #include <syscalls.h>
@@ -86,8 +87,32 @@ struct UndertakerEntry : DoublyLinkedListLinkImpl<UndertakerEntry> {
} }
}; };
class ThreadNotificationService : public DefaultNotificationService {
public:
ThreadNotificationService()
: DefaultNotificationService("threads")
{
}
void Notify(uint32 eventCode, struct thread* thread)
{
char eventBuffer[128];
KMessage event;
event.SetTo(eventBuffer, sizeof(eventBuffer), THREAD_MONITOR);
event.AddInt32("event", eventCode);
event.AddInt32("thread", thread->id);
event.AddPointer("threadStruct", thread);
DefaultNotificationService::Notify(event, eventCode);
}
};
static DoublyLinkedList<UndertakerEntry> sUndertakerEntries; static DoublyLinkedList<UndertakerEntry> sUndertakerEntries;
static ConditionVariable sUndertakerCondition; static ConditionVariable sUndertakerCondition;
static ThreadNotificationService sNotificationService;
// The dead queue is used as a pool from which to retrieve and reuse previously // The dead queue is used as a pool from which to retrieve and reuse previously
// allocated thread structs when creating a new thread. It should be gone once // allocated thread structs when creating a new thread. It should be gone once
@@ -504,6 +529,9 @@ create_thread(thread_creation_attributes& attributes, bool kernel)
thread->entry = attributes.entry; thread->entry = attributes.entry;
status = thread->id; status = thread->id;
// notify listeners
sNotificationService.Notify(THREAD_ADDED, thread);
if (kernel) { if (kernel) {
// this sets up an initial kthread stack that runs the entry // this sets up an initial kthread stack that runs the entry
@@ -1507,6 +1535,9 @@ thread_exit(void)
put_select_sync(sync); put_select_sync(sync);
} }
// notify listeners
sNotificationService.Notify(THREAD_REMOVED, thread);
// shutdown the thread messaging // shutdown the thread messaging
status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0); status = acquire_sem_etc(thread->msg.write_sem, 1, B_RELATIVE_TIMEOUT, 0);
@@ -1740,6 +1771,25 @@ thread_dequeue_id(struct thread_queue *q, thread_id id)
} }
struct thread*
thread_iterate_through_threads(thread_iterator_callback callback, void* cookie)
{
struct hash_iterator iterator;
hash_open(sThreadHash, &iterator);
struct thread* thread;
while ((thread = (struct thread*)hash_next(sThreadHash, &iterator))
!= NULL) {
if (callback(thread, cookie))
break;
}
hash_close(sThreadHash, &iterator, false);
return thread;
}
thread_id thread_id
allocate_thread_id(void) allocate_thread_id(void)
{ {
@@ -2099,6 +2149,9 @@ thread_init(kernel_args *args)
} }
sUsedThreads = args->num_cpus; sUsedThreads = args->num_cpus;
// init the notification service
new(&sNotificationService) ThreadNotificationService();
// 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");