1.1 --- a/libfsserver/lib/generic/notification.cc Sat Feb 25 18:10:13 2023 +0100
1.2 +++ b/libfsserver/lib/generic/notification.cc Sat Feb 25 22:11:08 2023 +0100
1.3 @@ -40,11 +40,28 @@
1.4 {
1.5 }
1.6
1.7 +/* Return an endpoint number, removing the mapping from the given notifier if
1.8 + indicated. */
1.9 +
1.10 +long NotificationSupport::_get_endpoint(l4_cap_idx_t notifier, bool remove, unsigned int *endpoint)
1.11 +{
1.12 + NotifierEndpointMap::iterator itp = _subscribers.find(notifier);
1.13 +
1.14 + if (itp == _subscribers.end())
1.15 + return -L4_ENOENT;
1.16 +
1.17 + *endpoint = itp->second;
1.18 +
1.19 + if (remove)
1.20 + _subscribers.erase(itp);
1.21 +
1.22 + return L4_EOK;
1.23 +}
1.24 +
1.25 /* Subscribe to notifications using a notification object, returning the
1.26 endpoint number. */
1.27
1.28 -long NotificationSupport::subscribe(l4_cap_idx_t notifier, notify_flags_t flags,
1.29 - void *subscriber, unsigned int *endpoint_number)
1.30 +long NotificationSupport::subscribe(l4_cap_idx_t notifier, notify_flags_t flags)
1.31 {
1.32 std::lock_guard<std::mutex> guard(_lock);
1.33
1.34 @@ -59,15 +76,14 @@
1.35 _endpoints[endpoint].deferred_values = _deferred_values;
1.36 }
1.37
1.38 - *endpoint_number = endpoint;
1.39 - return _subscribe(endpoint, notifier, flags, subscriber);
1.40 + return _subscribe(endpoint, notifier, flags);
1.41 }
1.42
1.43 /* Subscribe to a specific endpoint's notifications using a notification
1.44 object. */
1.45
1.46 long NotificationSupport::subscribe(unsigned int endpoint, l4_cap_idx_t notifier,
1.47 - notify_flags_t flags, void *subscriber)
1.48 + notify_flags_t flags)
1.49 {
1.50 std::lock_guard<std::mutex> guard(_lock);
1.51
1.52 @@ -82,22 +98,22 @@
1.53 _endpoints[endpoint].deferred_values = _deferred_values;
1.54 }
1.55
1.56 - return _subscribe(endpoint, notifier, flags, subscriber);
1.57 + return _subscribe(endpoint, notifier, flags);
1.58 }
1.59
1.60 /* Unsubscribe from an endpoint's notifications. */
1.61
1.62 -void NotificationSupport::unsubscribe(unsigned int endpoint, void *subscriber)
1.63 +void NotificationSupport::unsubscribe(l4_cap_idx_t notifier)
1.64 {
1.65 std::lock_guard<std::mutex> guard(_lock);
1.66
1.67 - _unsubscribe(endpoint, subscriber);
1.68 + _unsubscribe(notifier);
1.69 }
1.70
1.71 /* Common subscription functionality. */
1.72
1.73 long NotificationSupport::_subscribe(unsigned int endpoint, l4_cap_idx_t notifier,
1.74 - notify_flags_t flags, void *subscriber)
1.75 + notify_flags_t flags)
1.76 {
1.77 /* Record details of the notifier itself. */
1.78
1.79 @@ -115,28 +131,22 @@
1.80 ep.deferred_values = NOTIFY_VALUES_NULL;
1.81 }
1.82
1.83 - /* Record the subscriber's notifier. */
1.84 + /* Record the notifier's endpoint. */
1.85
1.86 - _subscribers[subscriber] = notifier;
1.87 + _subscribers[notifier] = endpoint;
1.88 return L4_EOK;
1.89 }
1.90
1.91 -void NotificationSupport::_unsubscribe(unsigned int endpoint, void *subscriber)
1.92 +void NotificationSupport::_unsubscribe(l4_cap_idx_t notifier)
1.93 {
1.94 - if (endpoint >= _endpoints.size())
1.95 - return;
1.96 -
1.97 - /* Find and remove the subscriber's notifier. */
1.98 + /* Find and remove the notifier endpoint record. */
1.99
1.100 - SubscriberNotifierMap::iterator itp = _subscribers.find(subscriber);
1.101 - l4_cap_idx_t notifier;
1.102 + unsigned int endpoint;
1.103 + long err = _get_endpoint(notifier, true, &endpoint);
1.104
1.105 - if (itp == _subscribers.end())
1.106 + if (err)
1.107 return;
1.108
1.109 - notifier = itp->second;
1.110 - _subscribers.erase(itp);
1.111 -
1.112 /* Release the notifier. */
1.113
1.114 NotificationEndpoint &ep = _endpoints[endpoint];
1.115 @@ -220,6 +230,29 @@
1.116 {
1.117 std::lock_guard<std::mutex> guard(_lock);
1.118
1.119 + _notify_others(endpoint, flags, values);
1.120 +}
1.121 +
1.122 +/* Notify the other endpoints given a notifier. */
1.123 +
1.124 +void NotificationSupport::notify_others(l4_cap_idx_t notifier, notify_flags_t flags,
1.125 + notify_values_t values)
1.126 +{
1.127 + std::lock_guard<std::mutex> guard(_lock);
1.128 +
1.129 + unsigned int endpoint;
1.130 + long err = _get_endpoint(notifier, false, &endpoint);
1.131 +
1.132 + if (err)
1.133 + return;
1.134 +
1.135 + _notify_others(endpoint, flags, values);
1.136 +}
1.137 +
1.138 +void NotificationSupport::_notify_others(unsigned int endpoint,
1.139 + notify_flags_t flags,
1.140 + notify_values_t values)
1.141 +{
1.142 for (unsigned int i = 0; i < _endpoints.size(); i++)
1.143 if (i != endpoint)
1.144 _notify(i, flags, values);