L4Re/departure

Changeset

534:99ce25bb6908
2023-03-21 Paul Boddie raw files shortlog changelog graph Changed notifier support to use resources instead of its own IPC handler.
libnotifier/Control (file) libnotifier/include/notifier/notifier.h (file) libnotifier/lib/src/Makefile (file) libnotifier/lib/src/notifier.cc (file)
     1.1 --- a/libnotifier/Control	Tue Mar 21 19:23:34 2023 +0100
     1.2 +++ b/libnotifier/Control	Tue Mar 21 21:49:00 2023 +0100
     1.3 @@ -1,3 +1,3 @@
     1.4 -requires: libstdc++ libc libipc
     1.5 +requires: libstdc++ libc libipc libfsserver
     1.6  provides: libnotifier
     1.7  maintainer: paul@boddie.org.uk
     2.1 --- a/libnotifier/include/notifier/notifier.h	Tue Mar 21 19:23:34 2023 +0100
     2.2 +++ b/libnotifier/include/notifier/notifier.h	Tue Mar 21 21:49:00 2023 +0100
     2.3 @@ -26,8 +26,11 @@
     2.4  #include <map>
     2.5  #include <mutex>
     2.6  
     2.7 +#include <fsserver/resource.h>
     2.8  #include <systypes/base.h>
     2.9  
    2.10 +#include "notifier_interface.h"
    2.11 +
    2.12  
    2.13  
    2.14  /* Object-specific notification details. */
    2.15 @@ -78,9 +81,9 @@
    2.16  
    2.17      ObjectNotificationStates _state;
    2.18  
    2.19 -    /* Notifier thread details. */
    2.20 +    /* Notifier resource details. */
    2.21  
    2.22 -    l4_cap_idx_t _thread = L4_INVALID_CAP;
    2.23 +    ipc_server_config_type *_config = NULL;
    2.24      bool _started = false;
    2.25  
    2.26      /* Convenience method to access object state. */
    2.27 @@ -89,9 +92,6 @@
    2.28  
    2.29      /* Helper methods. */
    2.30  
    2.31 -    virtual void _notify(notifiable_t *object, notify_flags_t flags,
    2.32 -                         notify_values_t values) = 0;
    2.33 -
    2.34      virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object);
    2.35  
    2.36  public:
    2.37 @@ -105,13 +105,12 @@
    2.38  
    2.39      virtual long unsubscribe(notifiable_t *object);
    2.40  
    2.41 -    virtual long get_endpoint(notifiable_t *object, l4_cap_idx_t *endpoint, bool create);
    2.42 -
    2.43      virtual long remove_endpoint(notifiable_t *object, l4_cap_idx_t endpoint);
    2.44  
    2.45 -    /* Event handling support. */
    2.46 +    /* Helper methods. */
    2.47  
    2.48 -    virtual void mainloop();
    2.49 +    virtual void notify(notifiable_t *object, notify_flags_t flags,
    2.50 +                        notify_values_t values) = 0;
    2.51  };
    2.52  
    2.53  
    2.54 @@ -136,15 +135,17 @@
    2.55  
    2.56      /* Helper methods. */
    2.57  
    2.58 -    virtual void _notify(notifiable_t *object, notify_flags_t flags,
    2.59 -                         notify_values_t values);
    2.60 -
    2.61      virtual bool _retrieve(notifiable_t **object);
    2.62  
    2.63      virtual bool _retrieve_for_object(notifiable_t *object);
    2.64  
    2.65  public:
    2.66      virtual long wait(notifiable_t **object);
    2.67 +
    2.68 +    /* Helper methods. */
    2.69 +
    2.70 +    virtual void notify(notifiable_t *object, notify_flags_t flags,
    2.71 +                        notify_values_t values);
    2.72  };
    2.73  
    2.74  
    2.75 @@ -153,14 +154,46 @@
    2.76  
    2.77  class SpecificObjectNotifier : public ObjectNotifier
    2.78  {
    2.79 -protected:
    2.80 +public:
    2.81 +    virtual long wait_object(notifiable_t *object);
    2.82 +
    2.83      /* Helper methods. */
    2.84  
    2.85 -    virtual void _notify(notifiable_t *object, notify_flags_t flags,
    2.86 -                         notify_values_t values);
    2.87 +    virtual void notify(notifiable_t *object, notify_flags_t flags,
    2.88 +                        notify_values_t values);
    2.89 +};
    2.90 +
    2.91 +
    2.92 +
    2.93 +/* Object-specific notifier resource. */
    2.94 +
    2.95 +class NotifierResource : public Notifier, public Resource
    2.96 +{
    2.97 +protected:
    2.98 +    ObjectNotifier *_notifier;
    2.99 +    notifiable_t *_object;
   2.100  
   2.101  public:
   2.102 -    virtual long wait_object(notifiable_t *object);
   2.103 +    explicit NotifierResource(ObjectNotifier *notifier, notifiable_t *object)
   2.104 +    : _notifier(notifier), _object(object)
   2.105 +    {
   2.106 +    }
   2.107 +
   2.108 +    explicit NotifierResource()
   2.109 +    : _notifier(NULL), _object(NULL)
   2.110 +    {
   2.111 +    }
   2.112 +
   2.113 +    /* Server details. */
   2.114 +
   2.115 +    virtual ipc_server_default_config_type config();
   2.116 +
   2.117 +    virtual void *interface()
   2.118 +    { return static_cast<Notifier *>(this); }
   2.119 +
   2.120 +    /* Notifier methods. */
   2.121 +
   2.122 +    virtual long notify(notify_flags_t flags, notify_values_t values);
   2.123  };
   2.124  
   2.125  
     3.1 --- a/libnotifier/lib/src/Makefile	Tue Mar 21 19:23:34 2023 +0100
     3.2 +++ b/libnotifier/lib/src/Makefile	Tue Mar 21 21:49:00 2023 +0100
     3.3 @@ -15,21 +15,26 @@
     3.4  
     3.5  # Individual interfaces.
     3.6  
     3.7 -CLIENT_INTERFACES_CC		= notifier notification
     3.8 +CLIENT_INTERFACES_CC		= notification
     3.9 +
    3.10 +SERVER_INTERFACES_CC		= notifier
    3.11  
    3.12  # Generated and plain source files.
    3.13  
    3.14  CLIENT_INTERFACES_SRC_CC	= $(call interfaces_to_client_cc,$(CLIENT_INTERFACES_CC))
    3.15  
    3.16 +SERVER_INTERFACES_SRC_CC	= $(call interfaces_to_server_cc,$(SERVER_INTERFACES_CC))
    3.17 +
    3.18  PLAIN_SRC_CC			= notifier.cc
    3.19  
    3.20  # Normal definitions.
    3.21  
    3.22  SRC_CC				= \
    3.23  				$(CLIENT_INTERFACES_SRC_CC) \
    3.24 +				$(SERVER_INTERFACES_SRC_CC) \
    3.25  				$(PLAIN_SRC_CC)
    3.26  
    3.27 -REQUIRES_LIBS	= l4re_c-util libipc libstdc++ libsystypes
    3.28 +REQUIRES_LIBS	= l4re_c-util libipc libstdc++ libsystypes libfsserver
    3.29  
    3.30  PRIVATE_INCDIR	= $(PKGDIR)/include/notifier $(IDL_BUILD_DIR) $(IDL_EXPORT_DIR)
    3.31  CONTRIB_INCDIR	= libnotifier
     4.1 --- a/libnotifier/lib/src/notifier.cc	Tue Mar 21 19:23:34 2023 +0100
     4.2 +++ b/libnotifier/lib/src/notifier.cc	Tue Mar 21 21:49:00 2023 +0100
     4.3 @@ -22,15 +22,13 @@
     4.4  #include <map>
     4.5  #include <mutex>
     4.6  
     4.7 +#include <fsserver/resource_server.h>
     4.8  #include <ipc/cap_alloc.h>
     4.9  #include <ipc/server.h>
    4.10  
    4.11 -#include <pthread.h>
    4.12 -#include <pthread-l4.h>
    4.13 -
    4.14  #include "notification_client.h"
    4.15  #include "notifier.h"
    4.16 -#include "notifier_interface.h"
    4.17 +#include "notifier_server.h"
    4.18  
    4.19  
    4.20  
    4.21 @@ -79,66 +77,13 @@
    4.22  
    4.23  
    4.24  
    4.25 -/* Invoke the mainloop in a thread. */
    4.26 -
    4.27 -static void *notifier_mainloop(void *data)
    4.28 -{
    4.29 -  ObjectNotifier *notifier = reinterpret_cast<ObjectNotifier *>(data);
    4.30 -
    4.31 -  notifier->mainloop();
    4.32 -  return 0;
    4.33 -}
    4.34 -
    4.35 -
    4.36 -
    4.37  /* Virtual destructor required for base class instance reference deletion. */
    4.38  
    4.39  ObjectNotifier::~ObjectNotifier()
    4.40  {
    4.41  }
    4.42  
    4.43 -/* Listen for notifications. */
    4.44  
    4.45 -void ObjectNotifier::mainloop()
    4.46 -{
    4.47 -  ipc_message_t msg;
    4.48 -  l4_umword_t label;
    4.49 -
    4.50 -  while (1)
    4.51 -  {
    4.52 -    ipc_message_wait(&msg, &label);
    4.53 -
    4.54 -    /* Clear lower label bits. */
    4.55 -
    4.56 -    label = label & ~3UL;
    4.57 -
    4.58 -    /* Ignore erroneous messages. */
    4.59 -
    4.60 -    if (l4_ipc_error(msg.tag, l4_utcb()))
    4.61 -      continue;
    4.62 -
    4.63 -    /* Interpret gate labels as notifiable objects. */
    4.64 -
    4.65 -    notifiable_t *object = (notifiable_t *) label;
    4.66 -
    4.67 -    /* Obtain message details. */
    4.68 -
    4.69 -    ipc_message_open(&msg);
    4.70 -
    4.71 -    struct in_words_Notifier_notify *in_words = (struct in_words_Notifier_notify *) ipc_message_get_word_address(&msg, 0);
    4.72 -
    4.73 -    /* Reply to notifications. */
    4.74 -
    4.75 -    ipc_message_reply(&msg);
    4.76 -    ipc_message_discard(&msg);
    4.77 -
    4.78 -    /* Register the notification. */
    4.79 -
    4.80 -    _notify(object, in_words->flags, in_words->values);
    4.81 -  }
    4.82 -
    4.83 -  ipc_message_free(&msg);
    4.84 -}
    4.85  
    4.86  /* Start listening for notifications. */
    4.87  
    4.88 @@ -147,18 +92,17 @@
    4.89    if (_started)
    4.90      return L4_EOK;
    4.91  
    4.92 -  pthread_t thread;
    4.93 -  pthread_attr_t attr;
    4.94 -  long err;
    4.95 +  /* Create a new thread to serve a "null" resource. This resource is not used
    4.96 +     for notifications but merely for control purposes. */
    4.97  
    4.98 -  pthread_attr_init(&attr);
    4.99 -  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
   4.100 +  NotifierResource *notifier = new NotifierResource;
   4.101 +  ResourceServer server(notifier);
   4.102 +  long err = server.start_thread(false);
   4.103  
   4.104 -  err = pthread_create(&thread, &attr, notifier_mainloop, this);
   4.105    if (err)
   4.106      return err;
   4.107  
   4.108 -  _thread = pthread_l4_cap(thread);
   4.109 +  _config = server.config();
   4.110    _started = true;
   4.111  
   4.112    return L4_EOK;
   4.113 @@ -188,66 +132,56 @@
   4.114  
   4.115  long ObjectNotifier::subscribe(notifiable_t *object, notify_flags_t flags)
   4.116  {
   4.117 -  l4_cap_idx_t endpoint;
   4.118 -  long err = get_endpoint(object, &endpoint, true);
   4.119 +  /* Acquire the lock for state lookup. */
   4.120 +
   4.121 +  std::unique_lock<std::mutex> state_guard(_state_lock);
   4.122 +
   4.123 +  /* Obtain potentially new state for the object. */
   4.124 +
   4.125 +  ObjectNotificationState &state = object_state(object, true);
   4.126  
   4.127 -  if (err)
   4.128 -    return err;
   4.129 +  if (state.is_null())
   4.130 +  {
   4.131 +    /* Serve the new object in the notifier thread. */
   4.132 +
   4.133 +    NotifierResource *resource = new NotifierResource(this, object);
   4.134 +    ResourceServer server(resource);
   4.135 +    long err = server.start_in_thread(_config->thread, false);
   4.136 +
   4.137 +    if (err)
   4.138 +      return err;
   4.139 +
   4.140 +    state.endpoint = server.config()->server;
   4.141 +  }
   4.142  
   4.143    /* Subscribe, sending the notification endpoint via the principal reference
   4.144       for the object. */
   4.145  
   4.146    client_Notification notify(object->base->ref);
   4.147  
   4.148 -  return notify.subscribe(endpoint, flags);
   4.149 +  return notify.subscribe(state.endpoint, flags);
   4.150  }
   4.151  
   4.152  /* Unsubscribe from notification events on an object. */
   4.153  
   4.154  long ObjectNotifier::unsubscribe(notifiable_t *object)
   4.155  {
   4.156 -  l4_cap_idx_t endpoint;
   4.157 -  long err = get_endpoint(object, &endpoint, false);
   4.158 +  /* Acquire the lock for state lookup. */
   4.159 +
   4.160 +  std::unique_lock<std::mutex> state_guard(_state_lock);
   4.161  
   4.162 -  if (err)
   4.163 -    return err;
   4.164 +  ObjectNotificationState &state = object_state(object, false);
   4.165 +
   4.166 +  if (state.is_null())
   4.167 +    return -L4_ENOENT;
   4.168  
   4.169    /* Unsubscribe via the notification interface. */
   4.170  
   4.171    client_Notification notify(object->base->ref);
   4.172  
   4.173 -  notify.unsubscribe(endpoint);
   4.174 -
   4.175 -  return remove_endpoint(object, endpoint);
   4.176 -}
   4.177 -
   4.178 -/* Obtain a notification endpoint for an object. */
   4.179 -
   4.180 -long ObjectNotifier::get_endpoint(notifiable_t *object, l4_cap_idx_t *endpoint, bool create)
   4.181 -{
   4.182 -  /* Acquire the lock for state lookup. */
   4.183 -
   4.184 -  std::unique_lock<std::mutex> state_guard(_state_lock);
   4.185 -
   4.186 -  ObjectNotificationState &state = object_state(object, create);
   4.187 +  notify.unsubscribe(state.endpoint);
   4.188  
   4.189 -  /* Create a notification endpoint, if necessary. */
   4.190 -
   4.191 -  if (state.is_null())
   4.192 -  {
   4.193 -    if (create)
   4.194 -    {
   4.195 -      long err = ipc_server_new_for_thread(&state.endpoint, object, _thread);
   4.196 -
   4.197 -      if (err)
   4.198 -        return err;
   4.199 -    }
   4.200 -    else
   4.201 -      return -L4_ENOENT;
   4.202 -  }
   4.203 -
   4.204 -  *endpoint = state.endpoint;
   4.205 -  return L4_EOK;
   4.206 +  return remove_endpoint(object, state.endpoint);
   4.207  }
   4.208  
   4.209  /* Remove a notification endpoint for an object. */
   4.210 @@ -274,8 +208,8 @@
   4.211     the generic server dispatch mechanism, with the gate label being interpreted
   4.212     and provided as the first parameter. */
   4.213  
   4.214 -void GeneralObjectNotifier::_notify(notifiable_t *object, notify_flags_t flags,
   4.215 -                                    notify_values_t values)
   4.216 +void GeneralObjectNotifier::notify(notifiable_t *object, notify_flags_t flags,
   4.217 +                                   notify_values_t values)
   4.218  {
   4.219    /* Enter critical section for the notifier (affecting all objects). */
   4.220  
   4.221 @@ -311,8 +245,8 @@
   4.222    _general_condition.notify_one();
   4.223  }
   4.224  
   4.225 -void SpecificObjectNotifier::_notify(notifiable_t *object, notify_flags_t flags,
   4.226 -                                     notify_values_t values)
   4.227 +void SpecificObjectNotifier::notify(notifiable_t *object, notify_flags_t flags,
   4.228 +                                    notify_values_t values)
   4.229  {
   4.230    /* Acquire the lock for state lookup. */
   4.231  
   4.232 @@ -455,4 +389,23 @@
   4.233    return L4_EOK;
   4.234  }
   4.235  
   4.236 +
   4.237 +
   4.238 +/* Object-specific resource methods. */
   4.239 +
   4.240 +ipc_server_default_config_type NotifierResource::config()
   4.241 +{
   4.242 +  return config_Notifier;
   4.243 +}
   4.244 +
   4.245 +/* Register a notification received by an object-specific resource. */
   4.246 +
   4.247 +long NotifierResource::notify(notify_flags_t flags, notify_values_t values)
   4.248 +{
   4.249 +  if (_notifier != NULL)
   4.250 +    _notifier->notify(_object, flags, values);
   4.251 +
   4.252 +  return L4_EOK;
   4.253 +}
   4.254 +
   4.255  // vim: tabstop=2 expandtab shiftwidth=2