1.1 --- a/libfsserver/include/fsserver/notification.h Tue Jul 13 23:18:37 2021 +0200
1.2 +++ b/libfsserver/include/fsserver/notification.h Fri Jul 16 00:38:55 2021 +0200
1.3 @@ -21,6 +21,7 @@
1.4
1.5 #pragma once
1.6
1.7 +#include <mutex>
1.8 #include <set>
1.9 #include <vector>
1.10
1.11 @@ -38,7 +39,7 @@
1.12 {
1.13 public:
1.14 NotifierSet notifiers;
1.15 - notify_flags_t flags, deferred;
1.16 + notify_flags_t flags = 0, deferred = 0;
1.17 };
1.18
1.19 typedef std::vector<NotificationEndpoint> NotificationEndpointList;
1.20 @@ -51,6 +52,8 @@
1.21 class NotificationSupport
1.22 {
1.23 protected:
1.24 + std::mutex _lock;
1.25 +
1.26 /* Endpoint count. */
1.27
1.28 unsigned int _min_endpoints;
1.29 @@ -59,8 +62,16 @@
1.30
1.31 NotificationEndpointList _endpoints;
1.32
1.33 + /* Deferred notifications for new endpoints. */
1.34 +
1.35 + notify_flags_t _deferred = 0;
1.36 +
1.37 virtual void release_notifiers();
1.38
1.39 + virtual void _notify(unsigned int endpoint, notify_flags_t flags);
1.40 +
1.41 + virtual void _subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags);
1.42 +
1.43 public:
1.44 explicit NotificationSupport(unsigned int endpoints=0);
1.45
1.46 @@ -68,6 +79,8 @@
1.47
1.48 virtual void notify_others(unsigned int endpoint, notify_flags_t flags);
1.49
1.50 + virtual unsigned int subscribe(l4_cap_idx_t notifier, notify_flags_t flags);
1.51 +
1.52 virtual void subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags);
1.53
1.54 virtual void unsubscribe(unsigned int endpoint, l4_cap_idx_t notifier);
2.1 --- a/libfsserver/lib/generic/notification.cc Tue Jul 13 23:18:37 2021 +0200
2.2 +++ b/libfsserver/lib/generic/notification.cc Fri Jul 16 00:38:55 2021 +0200
2.3 @@ -34,13 +34,51 @@
2.4 _endpoints.resize(_min_endpoints);
2.5 }
2.6
2.7 -/* Subscribe to an endpoint's notifications using a notification endpoint. */
2.8 +/* Subscribe to notifications using a notification object, returning the
2.9 + endpoint number. */
2.10 +
2.11 +unsigned int NotificationSupport::subscribe(l4_cap_idx_t notifier, notify_flags_t flags)
2.12 +{
2.13 + std::lock_guard<std::mutex> guard(_lock);
2.14 +
2.15 + unsigned int endpoint = _endpoints.size();
2.16 +
2.17 + _endpoints.resize(endpoint + 1);
2.18 +
2.19 + /* Propagate deferred flags for new endpoints. */
2.20 +
2.21 + if (_deferred)
2.22 + _endpoints[endpoint].deferred = _deferred;
2.23 +
2.24 + _subscribe(endpoint, notifier, flags);
2.25 +
2.26 + return endpoint;
2.27 +}
2.28 +
2.29 +/* Subscribe to a specific endpoint's notifications using a notification
2.30 + object. */
2.31
2.32 void NotificationSupport::subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags)
2.33 {
2.34 + std::lock_guard<std::mutex> guard(_lock);
2.35 +
2.36 if (endpoint >= _endpoints.size())
2.37 + {
2.38 _endpoints.resize(endpoint + 1);
2.39
2.40 + /* Propagate deferred flags for new endpoints. */
2.41 +
2.42 + if (_deferred)
2.43 + _endpoints[endpoint].deferred = _deferred;
2.44 + }
2.45 +
2.46 + _subscribe(endpoint, notifier, flags);
2.47 +}
2.48 +
2.49 +/* Common subscription functionality. */
2.50 +
2.51 +void NotificationSupport::_subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags)
2.52 +{
2.53 NotificationEndpoint &ep = _endpoints[endpoint];
2.54
2.55 ep.notifiers.insert(notifier);
2.56 @@ -50,7 +88,7 @@
2.57
2.58 if (ep.deferred)
2.59 {
2.60 - notify(endpoint, ep.deferred);
2.61 + _notify(endpoint, ep.deferred);
2.62 ep.deferred = 0;
2.63 }
2.64 }
2.65 @@ -59,6 +97,8 @@
2.66
2.67 void NotificationSupport::unsubscribe(unsigned int endpoint, l4_cap_idx_t notifier)
2.68 {
2.69 + std::lock_guard<std::mutex> guard(_lock);
2.70 +
2.71 if (endpoint >= _endpoints.size())
2.72 return;
2.73
2.74 @@ -82,6 +122,13 @@
2.75
2.76 void NotificationSupport::notify(unsigned int endpoint, notify_flags_t flags)
2.77 {
2.78 + std::lock_guard<std::mutex> guard(_lock);
2.79 +
2.80 + _notify(endpoint, flags);
2.81 +}
2.82 +
2.83 +void NotificationSupport::_notify(unsigned int endpoint, notify_flags_t flags)
2.84 +{
2.85 if (endpoint >= _endpoints.size())
2.86 return;
2.87
2.88 @@ -112,15 +159,21 @@
2.89
2.90 void NotificationSupport::notify_others(unsigned int endpoint, notify_flags_t flags)
2.91 {
2.92 + std::lock_guard<std::mutex> guard(_lock);
2.93 +
2.94 for (unsigned int i = 0; i < _endpoints.size(); i++)
2.95 if (i != endpoint)
2.96 - notify(i, flags);
2.97 + _notify(i, flags);
2.98 +
2.99 + _deferred |= flags;
2.100 }
2.101
2.102 /* Release notifiers for each endpoint. */
2.103
2.104 void NotificationSupport::release_notifiers()
2.105 {
2.106 + std::lock_guard<std::mutex> guard(_lock);
2.107 +
2.108 for (unsigned int endpoint = 0; endpoint < _endpoints.size(); endpoint++)
2.109 {
2.110 NotificationEndpoint &ep = _endpoints[endpoint];