* 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:
@@ -118,7 +118,7 @@ private:
|
||||
struct default_listener : public DoublyLinkedListLinkImpl<default_listener> {
|
||||
~default_listener();
|
||||
|
||||
uint32 flags;
|
||||
uint32 eventMask;
|
||||
team_id team;
|
||||
NotificationListener* listener;
|
||||
};
|
||||
@@ -131,7 +131,7 @@ public:
|
||||
DefaultNotificationService(const char* name);
|
||||
virtual ~DefaultNotificationService();
|
||||
|
||||
void Notify(const KMessage& event, uint32 flags);
|
||||
void Notify(const KMessage& event, uint32 eventMask);
|
||||
|
||||
virtual status_t AddListener(const KMessage* eventSpecifier,
|
||||
NotificationListener& listener);
|
||||
@@ -143,10 +143,10 @@ public:
|
||||
virtual const char* Name() { return fName; }
|
||||
|
||||
protected:
|
||||
virtual status_t _ToFlags(const KMessage& eventSpecifier,
|
||||
uint32& flags);
|
||||
virtual void _FirstAdded();
|
||||
virtual void _LastRemoved();
|
||||
virtual status_t ToEventMask(const KMessage& eventSpecifier,
|
||||
uint32& eventMask);
|
||||
virtual void FirstAdded();
|
||||
virtual void LastRemoved();
|
||||
|
||||
recursive_lock fLock;
|
||||
DefaultListenerList fListeners;
|
||||
@@ -168,7 +168,7 @@ public:
|
||||
NotificationListener& listener);
|
||||
|
||||
status_t RemoveUserListeners(port_id port, uint32 token);
|
||||
status_t UpdateUserListener(uint32 flags,
|
||||
status_t UpdateUserListener(uint32 eventMask,
|
||||
port_id port, uint32 token);
|
||||
|
||||
private:
|
||||
@@ -176,7 +176,7 @@ private:
|
||||
const KMessage* event);
|
||||
virtual void AllListenersNotified(
|
||||
NotificationService& service);
|
||||
status_t _AddListener(uint32 flags,
|
||||
status_t _AddListener(uint32 eventMask,
|
||||
NotificationListener& listener);
|
||||
|
||||
UserMessagingMessageSender fSender;
|
||||
|
||||
@@ -5,12 +5,32 @@
|
||||
#ifndef _KERNEL_IMAGE_H
|
||||
#define _KERNEL_IMAGE_H
|
||||
|
||||
|
||||
#include <image.h>
|
||||
|
||||
|
||||
struct image;
|
||||
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
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -20,6 +40,10 @@ extern status_t unregister_image(struct team *team, image_id id);
|
||||
extern int32 count_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,
|
||||
addr_t address, addr_t *_baseAddress, const char **_symbolName,
|
||||
const char **_imageName, bool *_exactMatch);
|
||||
|
||||
@@ -24,8 +24,8 @@ enum {
|
||||
|
||||
// port notifications
|
||||
#define PORT_MONITOR '_Pm_'
|
||||
#define PORT_ADDED 1
|
||||
#define PORT_REMOVED 2
|
||||
#define PORT_ADDED 0x01
|
||||
#define PORT_REMOVED 0x02
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
#include <thread_types.h>
|
||||
|
||||
|
||||
// Team notifications
|
||||
// team notifications
|
||||
#define TEAM_MONITOR '_Tm_'
|
||||
#define TEAM_ADDED 1
|
||||
#define TEAM_REMOVED 2
|
||||
#define TEAM_ADDED 0x01
|
||||
#define TEAM_REMOVED 0x02
|
||||
#define TEAM_EXEC 0x04
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -40,6 +41,10 @@ struct team *team_get_team_struct_locked(team_id id);
|
||||
int32 team_max_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,
|
||||
const char* const* env, int32 priority, team_id parentID, uint32 flags);
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ struct select_info;
|
||||
struct thread_creation_attributes;
|
||||
|
||||
|
||||
// thread notifications
|
||||
#define THREAD_MONITOR '_tm_'
|
||||
#define THREAD_ADDED 0x01
|
||||
#define THREAD_REMOVED 0x02
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -70,6 +76,10 @@ thread_is_idle_thread(struct thread *thread)
|
||||
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 peek_next_thread_id(void);
|
||||
|
||||
|
||||
@@ -27,10 +27,8 @@ public:
|
||||
void Notify(const KMessage& event);
|
||||
|
||||
protected:
|
||||
virtual status_t _ToFlags(const KMessage& eventSpecifier,
|
||||
uint32& flags);
|
||||
virtual void _FirstAdded();
|
||||
virtual void _LastRemoved();
|
||||
virtual void FirstAdded();
|
||||
virtual void LastRemoved();
|
||||
};
|
||||
|
||||
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
|
||||
NetNotificationService::_FirstAdded()
|
||||
NetNotificationService::FirstAdded()
|
||||
{
|
||||
// The reference counting doesn't work for us, as we'll have to
|
||||
// ensure our module stays loaded.
|
||||
@@ -82,7 +72,7 @@ NetNotificationService::_FirstAdded()
|
||||
|
||||
|
||||
void
|
||||
NetNotificationService::_LastRemoved()
|
||||
NetNotificationService::LastRemoved()
|
||||
{
|
||||
// Give up the reference _AddListener()
|
||||
put_module(NET_NOTIFICATIONS_MODULE_NAME);
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include <team.h>
|
||||
|
||||
|
||||
static const char* kEventMaskString = "event mask";
|
||||
|
||||
|
||||
NotificationManager NotificationManager::sManager;
|
||||
|
||||
|
||||
@@ -158,22 +161,28 @@ DefaultNotificationService::~DefaultNotificationService()
|
||||
|
||||
/*! \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
|
||||
\param eventMask Only listeners with an event mask sharing at least one
|
||||
common bit with this mask will receive the event.
|
||||
*/
|
||||
void
|
||||
DefaultNotificationService::Notify(const KMessage& event, uint32 flags)
|
||||
DefaultNotificationService::Notify(const KMessage& event, uint32 eventMask)
|
||||
{
|
||||
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();
|
||||
while (default_listener* listener = iterator.Next()) {
|
||||
if ((flags & listener->flags) != 0)
|
||||
if ((eventMask & listener->eventMask) != 0)
|
||||
listener->listener->EventOccured(*this, &event);
|
||||
}
|
||||
|
||||
// notify all listeners that all listeners have been notified
|
||||
iterator = fListeners.GetIterator();
|
||||
while (default_listener* listener = iterator.Next()) {
|
||||
if ((flags & listener->flags) != 0)
|
||||
if ((eventMask & listener->eventMask) != 0)
|
||||
listener->listener->AllListenersNotified(*this);
|
||||
}
|
||||
}
|
||||
@@ -186,8 +195,8 @@ DefaultNotificationService::AddListener(const KMessage* eventSpecifier,
|
||||
if (eventSpecifier == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
uint32 flags;
|
||||
status_t status = _ToFlags(*eventSpecifier, flags);
|
||||
uint32 eventMask;
|
||||
status_t status = ToEventMask(*eventSpecifier, eventMask);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
@@ -195,13 +204,13 @@ DefaultNotificationService::AddListener(const KMessage* eventSpecifier,
|
||||
if (listener == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
listener->flags = flags;
|
||||
listener->eventMask = eventMask;
|
||||
listener->team = -1;
|
||||
listener->listener = ¬ificationListener;
|
||||
|
||||
RecursiveLocker _(fLock);
|
||||
if (fListeners.IsEmpty())
|
||||
_FirstAdded();
|
||||
FirstAdded();
|
||||
fListeners.Add(listener);
|
||||
|
||||
return B_OK;
|
||||
@@ -227,9 +236,9 @@ DefaultNotificationService::RemoveListener(const KMessage* eventSpecifier,
|
||||
if (listener->listener == ¬ificationListener) {
|
||||
iterator.Remove();
|
||||
delete listener;
|
||||
|
||||
|
||||
if (fListeners.IsEmpty())
|
||||
_LastRemoved();
|
||||
LastRemoved();
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
@@ -239,21 +248,21 @@ DefaultNotificationService::RemoveListener(const KMessage* eventSpecifier,
|
||||
|
||||
|
||||
status_t
|
||||
DefaultNotificationService::_ToFlags(const KMessage& eventSpecifier,
|
||||
uint32& flags)
|
||||
DefaultNotificationService::ToEventMask(const KMessage& eventSpecifier,
|
||||
uint32& eventMask)
|
||||
{
|
||||
return eventSpecifier.FindInt32("flags", (int32*)&flags);
|
||||
return eventSpecifier.FindInt32("event mask", (int32*)&eventMask);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DefaultNotificationService::_FirstAdded()
|
||||
DefaultNotificationService::FirstAdded()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DefaultNotificationService::_LastRemoved()
|
||||
DefaultNotificationService::LastRemoved()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -281,9 +290,9 @@ DefaultUserNotificationService::AddListener(const KMessage* eventSpecifier,
|
||||
if (eventSpecifier == NULL)
|
||||
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)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
uint32 flags = eventSpecifier->GetInt32("flags", 0);
|
||||
bool addFlags = eventSpecifier->GetBool("add flags", false);
|
||||
uint32 eventMask = eventSpecifier->GetInt32(kEventMaskString, 0);
|
||||
bool addEvents = eventSpecifier->GetBool("add events", false);
|
||||
|
||||
RecursiveLocker _(fLock);
|
||||
|
||||
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
|
||||
while (default_listener* listener = iterator.Next()) {
|
||||
if (*listener->listener == notificationListener) {
|
||||
if (addFlags)
|
||||
listener->flags |= flags;
|
||||
if (addEvents)
|
||||
listener->eventMask |= eventMask;
|
||||
else
|
||||
listener->flags = flags;
|
||||
listener->eventMask = eventMask;
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
@@ -345,9 +354,9 @@ DefaultUserNotificationService::RemoveUserListeners(port_id port, uint32 token)
|
||||
if (*listener->listener == userListener) {
|
||||
iterator.Remove();
|
||||
delete listener;
|
||||
|
||||
|
||||
if (fListeners.IsEmpty())
|
||||
_LastRemoved();
|
||||
LastRemoved();
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
@@ -357,8 +366,8 @@ DefaultUserNotificationService::RemoveUserListeners(port_id port, uint32 token)
|
||||
|
||||
|
||||
status_t
|
||||
DefaultUserNotificationService::UpdateUserListener(uint32 flags, port_id port,
|
||||
uint32 token)
|
||||
DefaultUserNotificationService::UpdateUserListener(uint32 eventMask,
|
||||
port_id port, uint32 token)
|
||||
{
|
||||
UserMessagingListener userListener(fSender, port, token);
|
||||
|
||||
@@ -367,7 +376,7 @@ DefaultUserNotificationService::UpdateUserListener(uint32 flags, port_id port,
|
||||
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
|
||||
while (default_listener* listener = iterator.Next()) {
|
||||
if (*listener->listener == userListener) {
|
||||
listener->flags |= flags;
|
||||
listener->eventMask |= eventMask;
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
@@ -377,7 +386,7 @@ DefaultUserNotificationService::UpdateUserListener(uint32 flags, port_id port,
|
||||
if (copiedListener == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
status_t status = _AddListener(flags, *copiedListener);
|
||||
status_t status = _AddListener(eventMask, *copiedListener);
|
||||
if (status != B_OK)
|
||||
delete copiedListener;
|
||||
|
||||
@@ -389,13 +398,13 @@ void
|
||||
DefaultUserNotificationService::EventOccured(NotificationService& service,
|
||||
const KMessage* event)
|
||||
{
|
||||
int32 opcode = event->GetInt32("opcode", -1);
|
||||
int32 eventCode = event->GetInt32("event", -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
|
||||
RecursiveLocker _(fLock);
|
||||
|
||||
|
||||
DefaultListenerList::Iterator iterator = fListeners.GetIterator();
|
||||
while (default_listener* listener = iterator.Next()) {
|
||||
if (listener->team == team) {
|
||||
@@ -415,20 +424,20 @@ DefaultUserNotificationService::AllListenersNotified(
|
||||
|
||||
|
||||
status_t
|
||||
DefaultUserNotificationService::_AddListener(uint32 flags,
|
||||
DefaultUserNotificationService::_AddListener(uint32 eventMask,
|
||||
NotificationListener& notificationListener)
|
||||
{
|
||||
default_listener* listener = new(std::nothrow) default_listener;
|
||||
if (listener == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
listener->flags = flags;
|
||||
listener->eventMask = eventMask;
|
||||
listener->team = team_get_current_team_id();
|
||||
listener->listener = ¬ificationListener;
|
||||
|
||||
RecursiveLocker _(fLock);
|
||||
if (fListeners.IsEmpty())
|
||||
_FirstAdded();
|
||||
FirstAdded();
|
||||
fListeners.Add(listener);
|
||||
|
||||
return B_OK;
|
||||
@@ -511,7 +520,7 @@ NotificationManager::AddListener(const char* serviceName,
|
||||
char buffer[96];
|
||||
KMessage specifier;
|
||||
specifier.SetTo(buffer, sizeof(buffer), 0);
|
||||
specifier.AddInt32("event mask", eventMask);
|
||||
specifier.AddInt32(kEventMaskString, eventMask);
|
||||
|
||||
return AddListener(serviceName, &specifier, listener);
|
||||
}
|
||||
@@ -540,7 +549,7 @@ NotificationManager::UpdateListener(const char* serviceName,
|
||||
char buffer[96];
|
||||
KMessage specifier;
|
||||
specifier.SetTo(buffer, sizeof(buffer), 0);
|
||||
specifier.AddInt32("event mask", eventMask);
|
||||
specifier.AddInt32(kEventMaskString, eventMask);
|
||||
|
||||
return UpdateListener(serviceName, &specifier, listener);
|
||||
}
|
||||
|
||||
@@ -195,13 +195,6 @@ public:
|
||||
virtual ~DiskNotifications()
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
status_t _ToFlags(const KMessage& eventSpecifier, uint32& flags)
|
||||
{
|
||||
flags = eventSpecifier.GetInt32("flags", 0);
|
||||
return B_OK;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@
|
||||
#include <kimage.h>
|
||||
#include <kscheduler.h>
|
||||
#include <lock.h>
|
||||
#include <Notifications.h>
|
||||
#include <team.h>
|
||||
#include <thread.h>
|
||||
#include <thread_types.h>
|
||||
#include <user_debugger.h>
|
||||
#include <util/OpenHashTable.h>
|
||||
#include <util/AutoLock.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -31,14 +32,6 @@
|
||||
|
||||
#define ADD_DEBUGGER_COMMANDS
|
||||
|
||||
struct image {
|
||||
struct image* next;
|
||||
struct image* prev;
|
||||
HashTableLink<image> hash_link;
|
||||
image_info info;
|
||||
team_id team;
|
||||
};
|
||||
|
||||
|
||||
struct ImageTableDefinition {
|
||||
typedef image_id KeyType;
|
||||
@@ -55,9 +48,31 @@ struct ImageTableDefinition {
|
||||
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 mutex sImageMutex = MUTEX_INITIALIZER("image");
|
||||
static ImageTable* sImageTable;
|
||||
static ImageNotificationService sNotificationService;
|
||||
|
||||
|
||||
/*! 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);
|
||||
sImageTable->Insert(image);
|
||||
|
||||
// notify listeners
|
||||
sNotificationService.Notify(IMAGE_ADDED, image);
|
||||
|
||||
mutex_unlock(&sImageMutex);
|
||||
|
||||
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
|
||||
user_debug_image_deleted(&image->info);
|
||||
|
||||
// notify listeners
|
||||
sNotificationService.Notify(IMAGE_REMOVED, image);
|
||||
|
||||
free(image);
|
||||
}
|
||||
|
||||
@@ -263,6 +284,22 @@ dump_images_list(int argc, char **argv)
|
||||
#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
|
||||
image_debug_lookup_user_symbol_address(struct team *team, addr_t address,
|
||||
addr_t *_baseAddress, const char **_symbolName, const char **_imageName,
|
||||
@@ -310,6 +347,8 @@ image_init(void)
|
||||
return error;
|
||||
}
|
||||
|
||||
new(&sNotificationService) ImageNotificationService();
|
||||
|
||||
#ifdef ADD_DEBUGGER_COMMANDS
|
||||
add_debugger_command("team_images", &dump_images_list, "Dump all registered images from the current team");
|
||||
#endif
|
||||
|
||||
@@ -65,10 +65,6 @@ public:
|
||||
PortNotificationService();
|
||||
|
||||
void Notify(uint32 opcode, port_id team);
|
||||
|
||||
protected:
|
||||
virtual status_t _ToFlags(const KMessage& eventSpecifier,
|
||||
uint32& flags);
|
||||
};
|
||||
|
||||
#define MAX_QUEUE_LENGTH 4096
|
||||
@@ -109,18 +105,10 @@ 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("event", opcode);
|
||||
event.AddInt32("port", port);
|
||||
|
||||
DefaultNotificationService::Notify(event, ~0U);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
PortNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
|
||||
{
|
||||
flags = ~0U;
|
||||
return B_OK;
|
||||
DefaultNotificationService::Notify(event, opcode);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+37
-19
@@ -86,11 +86,7 @@ class TeamNotificationService : public DefaultNotificationService {
|
||||
public:
|
||||
TeamNotificationService();
|
||||
|
||||
void Notify(uint32 opcode, team_id team);
|
||||
|
||||
protected:
|
||||
virtual status_t _ToFlags(const KMessage& eventSpecifier,
|
||||
uint32& flags);
|
||||
void Notify(uint32 eventCode, struct team* team);
|
||||
};
|
||||
|
||||
|
||||
@@ -312,23 +308,16 @@ TeamNotificationService::TeamNotificationService()
|
||||
|
||||
|
||||
void
|
||||
TeamNotificationService::Notify(uint32 opcode, team_id team)
|
||||
TeamNotificationService::Notify(uint32 eventCode, struct team* team)
|
||||
{
|
||||
char eventBuffer[64];
|
||||
char eventBuffer[128];
|
||||
KMessage event;
|
||||
event.SetTo(eventBuffer, sizeof(eventBuffer), TEAM_MONITOR);
|
||||
event.AddInt32("opcode", opcode);
|
||||
event.AddInt32("team", team);
|
||||
event.AddInt32("event", eventCode);
|
||||
event.AddInt32("team", team->id);
|
||||
event.AddPointer("teamStruct", team);
|
||||
|
||||
DefaultNotificationService::Notify(event, ~0U);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
TeamNotificationService::_ToFlags(const KMessage& eventSpecifier, uint32& flags)
|
||||
{
|
||||
flags = ~0U;
|
||||
return B_OK;
|
||||
DefaultNotificationService::Notify(event, eventCode);
|
||||
}
|
||||
|
||||
|
||||
@@ -1236,6 +1225,9 @@ load_image_internal(char**& _flatArgs, size_t flatArgsSize, int32 argCount,
|
||||
if (status != B_OK)
|
||||
goto err4;
|
||||
|
||||
// notify team listeners
|
||||
sNotificationService.Notify(TEAM_ADDED, team);
|
||||
|
||||
// Create a kernel thread, but under the context of the new team
|
||||
// The new thread will take over ownership of teamArgs
|
||||
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();
|
||||
|
||||
// notify team listeners
|
||||
sNotificationService.Notify(TEAM_EXEC, team);
|
||||
|
||||
status = team_create_thread_start(teamArgs);
|
||||
// this one usually doesn't return...
|
||||
|
||||
@@ -1603,6 +1598,9 @@ fork_team(void)
|
||||
goto err5;
|
||||
}
|
||||
|
||||
// notify team listeners
|
||||
sNotificationService.Notify(TEAM_ADDED, team);
|
||||
|
||||
// create a kernel thread under the context of the new team
|
||||
threadID = spawn_kernel_thread_etc(fork_team_thread_start,
|
||||
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.
|
||||
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
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <kimage.h>
|
||||
#include <kscheduler.h>
|
||||
#include <ksignal.h>
|
||||
#include <Notifications.h>
|
||||
#include <real_time_clock.h>
|
||||
#include <smp.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 ConditionVariable sUndertakerCondition;
|
||||
static ThreadNotificationService sNotificationService;
|
||||
|
||||
|
||||
// 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
|
||||
@@ -504,6 +529,9 @@ create_thread(thread_creation_attributes& attributes, bool kernel)
|
||||
thread->entry = attributes.entry;
|
||||
status = thread->id;
|
||||
|
||||
// notify listeners
|
||||
sNotificationService.Notify(THREAD_ADDED, thread);
|
||||
|
||||
if (kernel) {
|
||||
// this sets up an initial kthread stack that runs the entry
|
||||
|
||||
@@ -1507,6 +1535,9 @@ thread_exit(void)
|
||||
put_select_sync(sync);
|
||||
}
|
||||
|
||||
// notify listeners
|
||||
sNotificationService.Notify(THREAD_REMOVED, thread);
|
||||
|
||||
// shutdown the thread messaging
|
||||
|
||||
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
|
||||
allocate_thread_id(void)
|
||||
{
|
||||
@@ -2099,6 +2149,9 @@ thread_init(kernel_args *args)
|
||||
}
|
||||
sUsedThreads = args->num_cpus;
|
||||
|
||||
// init the notification service
|
||||
new(&sNotificationService) ThreadNotificationService();
|
||||
|
||||
// start the undertaker thread
|
||||
new(&sUndertakerEntries) DoublyLinkedList<UndertakerEntry>();
|
||||
sUndertakerCondition.Init(&sUndertakerEntries, "undertaker entries");
|
||||
|
||||
Reference in New Issue
Block a user