1.1 --- a/libfsclient/lib/src/notifier.cc Sat Feb 18 22:48:39 2023 +0100
1.2 +++ b/libfsclient/lib/src/notifier.cc Thu Feb 23 23:49:26 2023 +0100
1.3 @@ -188,51 +188,29 @@
1.4
1.5 long ObjectNotifier::subscribe(notifiable_t *object, notify_flags_t flags)
1.6 {
1.7 - /* Acquire the lock for state lookup. */
1.8 -
1.9 - std::unique_lock<std::mutex> state_guard(_state_lock);
1.10 -
1.11 - ObjectNotificationState &state = object_state(object, true);
1.12 - long err;
1.13 -
1.14 - /* Create a notification endpoint, if necessary. */
1.15 + l4_cap_idx_t endpoint;
1.16 + long err = get_endpoint(object, &endpoint, true);
1.17
1.18 - if (state.is_null())
1.19 - {
1.20 - err = ipc_server_new_for_thread(&state.endpoint, object, _thread);
1.21 + if (err)
1.22 + return err;
1.23
1.24 - if (err)
1.25 - return err;
1.26 - }
1.27 -
1.28 - /* Subscribe, sending the notification endpoint. */
1.29 + /* Subscribe, sending the notification endpoint via the principal reference
1.30 + for the object. */
1.31
1.32 client_Notification notify(object->base->ref);
1.33
1.34 - err = notify.subscribe(state.endpoint, flags);
1.35 -
1.36 - if (err)
1.37 - {
1.38 - ipc_cap_free_um(state.endpoint);
1.39 - _state.erase(object);
1.40 - return err;
1.41 - }
1.42 -
1.43 - return L4_EOK;
1.44 + return notify.subscribe(endpoint, flags);
1.45 }
1.46
1.47 /* Unsubscribe from notification events on an object. */
1.48
1.49 long ObjectNotifier::unsubscribe(notifiable_t *object)
1.50 {
1.51 - /* Acquire the lock for state lookup. */
1.52 -
1.53 - std::unique_lock<std::mutex> state_guard(_state_lock);
1.54 + l4_cap_idx_t endpoint;
1.55 + long err = get_endpoint(object, &endpoint, false);
1.56
1.57 - ObjectNotificationState &state = object_state(object, false);
1.58 -
1.59 - if (state.is_null())
1.60 - return -L4_EINVAL;
1.61 + if (err)
1.62 + return err;
1.63
1.64 /* Unsubscribe via the notification interface. */
1.65
1.66 @@ -240,7 +218,46 @@
1.67
1.68 notify.unsubscribe();
1.69
1.70 - ipc_cap_free_um(state.endpoint);
1.71 + return remove_endpoint(object, endpoint);
1.72 +}
1.73 +
1.74 +/* Obtain a notification endpoint for an object. */
1.75 +
1.76 +long ObjectNotifier::get_endpoint(notifiable_t *object, l4_cap_idx_t *endpoint, bool create)
1.77 +{
1.78 + /* Acquire the lock for state lookup. */
1.79 +
1.80 + std::unique_lock<std::mutex> state_guard(_state_lock);
1.81 +
1.82 + ObjectNotificationState &state = object_state(object, create);
1.83 +
1.84 + /* Create a notification endpoint, if necessary. */
1.85 +
1.86 + if (state.is_null())
1.87 + {
1.88 + if (create)
1.89 + {
1.90 + long err = ipc_server_new_for_thread(&state.endpoint, object, _thread);
1.91 +
1.92 + if (err)
1.93 + return err;
1.94 + }
1.95 + else
1.96 + return -L4_ENOENT;
1.97 + }
1.98 +
1.99 + *endpoint = state.endpoint;
1.100 + return L4_EOK;
1.101 +}
1.102 +
1.103 +/* Remove a notification endpoint for an object. */
1.104 +
1.105 +long ObjectNotifier::remove_endpoint(notifiable_t *object, l4_cap_idx_t endpoint)
1.106 +{
1.107 + if (l4_is_invalid_cap(endpoint))
1.108 + return -L4_EINVAL;
1.109 +
1.110 + ipc_cap_free_um(endpoint);
1.111
1.112 _state.erase(object);
1.113