# HG changeset patch # User Paul Boddie # Date 1679431740 -3600 # Node ID 99ce25bb6908a3d12a10917db5eb2d9eeef9cbbb # Parent 2a71834ac302a86735681ab264c7507fe73c557c Changed notifier support to use resources instead of its own IPC handler. diff -r 2a71834ac302 -r 99ce25bb6908 libnotifier/Control --- a/libnotifier/Control Tue Mar 21 19:23:34 2023 +0100 +++ b/libnotifier/Control Tue Mar 21 21:49:00 2023 +0100 @@ -1,3 +1,3 @@ -requires: libstdc++ libc libipc +requires: libstdc++ libc libipc libfsserver provides: libnotifier maintainer: paul@boddie.org.uk diff -r 2a71834ac302 -r 99ce25bb6908 libnotifier/include/notifier/notifier.h --- a/libnotifier/include/notifier/notifier.h Tue Mar 21 19:23:34 2023 +0100 +++ b/libnotifier/include/notifier/notifier.h Tue Mar 21 21:49:00 2023 +0100 @@ -26,8 +26,11 @@ #include #include +#include #include +#include "notifier_interface.h" + /* Object-specific notification details. */ @@ -78,9 +81,9 @@ ObjectNotificationStates _state; - /* Notifier thread details. */ + /* Notifier resource details. */ - l4_cap_idx_t _thread = L4_INVALID_CAP; + ipc_server_config_type *_config = NULL; bool _started = false; /* Convenience method to access object state. */ @@ -89,9 +92,6 @@ /* Helper methods. */ - virtual void _notify(notifiable_t *object, notify_flags_t flags, - notify_values_t values) = 0; - virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object); public: @@ -105,13 +105,12 @@ virtual long unsubscribe(notifiable_t *object); - virtual long get_endpoint(notifiable_t *object, l4_cap_idx_t *endpoint, bool create); - virtual long remove_endpoint(notifiable_t *object, l4_cap_idx_t endpoint); - /* Event handling support. */ + /* Helper methods. */ - virtual void mainloop(); + virtual void notify(notifiable_t *object, notify_flags_t flags, + notify_values_t values) = 0; }; @@ -136,15 +135,17 @@ /* Helper methods. */ - virtual void _notify(notifiable_t *object, notify_flags_t flags, - notify_values_t values); - virtual bool _retrieve(notifiable_t **object); virtual bool _retrieve_for_object(notifiable_t *object); public: virtual long wait(notifiable_t **object); + + /* Helper methods. */ + + virtual void notify(notifiable_t *object, notify_flags_t flags, + notify_values_t values); }; @@ -153,14 +154,46 @@ class SpecificObjectNotifier : public ObjectNotifier { -protected: +public: + virtual long wait_object(notifiable_t *object); + /* Helper methods. */ - virtual void _notify(notifiable_t *object, notify_flags_t flags, - notify_values_t values); + virtual void notify(notifiable_t *object, notify_flags_t flags, + notify_values_t values); +}; + + + +/* Object-specific notifier resource. */ + +class NotifierResource : public Notifier, public Resource +{ +protected: + ObjectNotifier *_notifier; + notifiable_t *_object; public: - virtual long wait_object(notifiable_t *object); + explicit NotifierResource(ObjectNotifier *notifier, notifiable_t *object) + : _notifier(notifier), _object(object) + { + } + + explicit NotifierResource() + : _notifier(NULL), _object(NULL) + { + } + + /* Server details. */ + + virtual ipc_server_default_config_type config(); + + virtual void *interface() + { return static_cast(this); } + + /* Notifier methods. */ + + virtual long notify(notify_flags_t flags, notify_values_t values); }; diff -r 2a71834ac302 -r 99ce25bb6908 libnotifier/lib/src/Makefile --- a/libnotifier/lib/src/Makefile Tue Mar 21 19:23:34 2023 +0100 +++ b/libnotifier/lib/src/Makefile Tue Mar 21 21:49:00 2023 +0100 @@ -15,21 +15,26 @@ # Individual interfaces. -CLIENT_INTERFACES_CC = notifier notification +CLIENT_INTERFACES_CC = notification + +SERVER_INTERFACES_CC = notifier # Generated and plain source files. CLIENT_INTERFACES_SRC_CC = $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC)) +SERVER_INTERFACES_SRC_CC = $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC)) + PLAIN_SRC_CC = notifier.cc # Normal definitions. SRC_CC = \ $(CLIENT_INTERFACES_SRC_CC) \ + $(SERVER_INTERFACES_SRC_CC) \ $(PLAIN_SRC_CC) -REQUIRES_LIBS = l4re_c-util libipc libstdc++ libsystypes +REQUIRES_LIBS = l4re_c-util libipc libstdc++ libsystypes libfsserver PRIVATE_INCDIR = $(PKGDIR)/include/notifier $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR) CONTRIB_INCDIR = libnotifier diff -r 2a71834ac302 -r 99ce25bb6908 libnotifier/lib/src/notifier.cc --- a/libnotifier/lib/src/notifier.cc Tue Mar 21 19:23:34 2023 +0100 +++ b/libnotifier/lib/src/notifier.cc Tue Mar 21 21:49:00 2023 +0100 @@ -22,15 +22,13 @@ #include #include +#include #include #include -#include -#include - #include "notification_client.h" #include "notifier.h" -#include "notifier_interface.h" +#include "notifier_server.h" @@ -79,66 +77,13 @@ -/* Invoke the mainloop in a thread. */ - -static void *notifier_mainloop(void *data) -{ - ObjectNotifier *notifier = reinterpret_cast(data); - - notifier->mainloop(); - return 0; -} - - - /* Virtual destructor required for base class instance reference deletion. */ ObjectNotifier::~ObjectNotifier() { } -/* Listen for notifications. */ -void ObjectNotifier::mainloop() -{ - ipc_message_t msg; - l4_umword_t label; - - while (1) - { - ipc_message_wait(&msg, &label); - - /* Clear lower label bits. */ - - label = label & ~3UL; - - /* Ignore erroneous messages. */ - - if (l4_ipc_error(msg.tag, l4_utcb())) - continue; - - /* Interpret gate labels as notifiable objects. */ - - notifiable_t *object = (notifiable_t *) label; - - /* Obtain message details. */ - - ipc_message_open(&msg); - - struct in_words_Notifier_notify *in_words = (struct in_words_Notifier_notify *) ipc_message_get_word_address(&msg, 0); - - /* Reply to notifications. */ - - ipc_message_reply(&msg); - ipc_message_discard(&msg); - - /* Register the notification. */ - - _notify(object, in_words->flags, in_words->values); - } - - ipc_message_free(&msg); -} /* Start listening for notifications. */ @@ -147,18 +92,17 @@ if (_started) return L4_EOK; - pthread_t thread; - pthread_attr_t attr; - long err; + /* Create a new thread to serve a "null" resource. This resource is not used + for notifications but merely for control purposes. */ - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + NotifierResource *notifier = new NotifierResource; + ResourceServer server(notifier); + long err = server.start_thread(false); - err = pthread_create(&thread, &attr, notifier_mainloop, this); if (err) return err; - _thread = pthread_l4_cap(thread); + _config = server.config(); _started = true; return L4_EOK; @@ -188,66 +132,56 @@ long ObjectNotifier::subscribe(notifiable_t *object, notify_flags_t flags) { - l4_cap_idx_t endpoint; - long err = get_endpoint(object, &endpoint, true); + /* Acquire the lock for state lookup. */ + + std::unique_lock state_guard(_state_lock); + + /* Obtain potentially new state for the object. */ + + ObjectNotificationState &state = object_state(object, true); - if (err) - return err; + if (state.is_null()) + { + /* Serve the new object in the notifier thread. */ + + NotifierResource *resource = new NotifierResource(this, object); + ResourceServer server(resource); + long err = server.start_in_thread(_config->thread, false); + + if (err) + return err; + + state.endpoint = server.config()->server; + } /* Subscribe, sending the notification endpoint via the principal reference for the object. */ client_Notification notify(object->base->ref); - return notify.subscribe(endpoint, flags); + return notify.subscribe(state.endpoint, flags); } /* Unsubscribe from notification events on an object. */ long ObjectNotifier::unsubscribe(notifiable_t *object) { - l4_cap_idx_t endpoint; - long err = get_endpoint(object, &endpoint, false); + /* Acquire the lock for state lookup. */ + + std::unique_lock state_guard(_state_lock); - if (err) - return err; + ObjectNotificationState &state = object_state(object, false); + + if (state.is_null()) + return -L4_ENOENT; /* Unsubscribe via the notification interface. */ client_Notification notify(object->base->ref); - notify.unsubscribe(endpoint); - - return remove_endpoint(object, endpoint); -} - -/* Obtain a notification endpoint for an object. */ - -long ObjectNotifier::get_endpoint(notifiable_t *object, l4_cap_idx_t *endpoint, bool create) -{ - /* Acquire the lock for state lookup. */ - - std::unique_lock state_guard(_state_lock); - - ObjectNotificationState &state = object_state(object, create); + notify.unsubscribe(state.endpoint); - /* Create a notification endpoint, if necessary. */ - - if (state.is_null()) - { - if (create) - { - long err = ipc_server_new_for_thread(&state.endpoint, object, _thread); - - if (err) - return err; - } - else - return -L4_ENOENT; - } - - *endpoint = state.endpoint; - return L4_EOK; + return remove_endpoint(object, state.endpoint); } /* Remove a notification endpoint for an object. */ @@ -274,8 +208,8 @@ the generic server dispatch mechanism, with the gate label being interpreted and provided as the first parameter. */ -void GeneralObjectNotifier::_notify(notifiable_t *object, notify_flags_t flags, - notify_values_t values) +void GeneralObjectNotifier::notify(notifiable_t *object, notify_flags_t flags, + notify_values_t values) { /* Enter critical section for the notifier (affecting all objects). */ @@ -311,8 +245,8 @@ _general_condition.notify_one(); } -void SpecificObjectNotifier::_notify(notifiable_t *object, notify_flags_t flags, - notify_values_t values) +void SpecificObjectNotifier::notify(notifiable_t *object, notify_flags_t flags, + notify_values_t values) { /* Acquire the lock for state lookup. */ @@ -455,4 +389,23 @@ return L4_EOK; } + + +/* Object-specific resource methods. */ + +ipc_server_default_config_type NotifierResource::config() +{ + return config_Notifier; +} + +/* Register a notification received by an object-specific resource. */ + +long NotifierResource::notify(notify_flags_t flags, notify_values_t values) +{ + if (_notifier != NULL) + _notifier->notify(_object, flags, values); + + return L4_EOK; +} + // vim: tabstop=2 expandtab shiftwidth=2