1 /* 2 * Generic object event notification support. 3 * 4 * Copyright (C) 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #pragma once 23 24 #include <condition_variable> 25 #include <list> 26 #include <map> 27 #include <mutex> 28 29 #include <resource/resource.h> 30 #include <systypes/base.h> 31 32 #include "notifier_interface.h" 33 34 35 36 /* Object-specific notification details. */ 37 38 class ObjectNotificationState 39 { 40 public: 41 /* Synchronisation primitives for state access and notification. */ 42 43 std::mutex lock; 44 std::condition_variable condition; 45 46 /* Pending notifications for monitored objects. */ 47 48 notify_flags_t pending_notifications = 0; 49 notify_values_t pending_values = NOTIFY_VALUES_NULL; 50 51 /* Endpoints associated with monitored objects. */ 52 53 l4_cap_idx_t endpoint = L4_INVALID_CAP; 54 55 bool is_null() { return l4_is_invalid_cap(endpoint); } 56 }; 57 58 59 60 /* Collection types. */ 61 62 typedef std::map<notifiable_t *, ObjectNotificationState> ObjectNotificationStates; 63 typedef std::map<notifiable_t *, std::mutex> ObjectStateLocks; 64 65 66 67 /* An object for monitoring object event notifications. */ 68 69 class ObjectNotifier 70 { 71 protected: 72 /* General state access locking. */ 73 74 std::mutex _state_lock; 75 76 /* Object-specific state locking. */ 77 78 ObjectStateLocks _object_locks; 79 80 /* Notification state. */ 81 82 ObjectNotificationStates _state; 83 84 /* Notifier resource details. */ 85 86 ipc_server_config_type *_config = NULL; 87 bool _started = false; 88 89 /* Convenience method to access object state. */ 90 91 virtual ObjectNotificationState &object_state(notifiable_t *object, bool create); 92 93 /* Helper methods. */ 94 95 virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object); 96 97 public: 98 virtual ~ObjectNotifier(); 99 100 /* Local operations. */ 101 102 virtual long start(); 103 104 virtual long subscribe(notifiable_t *object, notify_flags_t flags); 105 106 virtual long unsubscribe(notifiable_t *object); 107 108 virtual long remove_endpoint(notifiable_t *object, l4_cap_idx_t endpoint); 109 110 /* Helper methods. */ 111 112 virtual void notify(notifiable_t *object, notify_flags_t flags, 113 notify_values_t values) = 0; 114 }; 115 116 117 118 /* An object monitoring notifications for a collection of different objects. */ 119 120 class GeneralObjectNotifier : public ObjectNotifier 121 { 122 protected: 123 /* Locking to protect pending notification members and to coordinate access 124 to notifications. */ 125 126 std::mutex _general_lock; 127 128 /* General lock synchronisation. */ 129 130 std::condition_variable _general_condition; 131 132 /* Objects affected by notifications. */ 133 134 std::list<notifiable_t *> _affected; 135 136 /* Helper methods. */ 137 138 virtual bool _retrieve(notifiable_t **object); 139 140 virtual bool _retrieve_for_object(notifiable_t *object); 141 142 public: 143 virtual long wait(notifiable_t **object); 144 145 /* Helper methods. */ 146 147 virtual void notify(notifiable_t *object, notify_flags_t flags, 148 notify_values_t values); 149 }; 150 151 152 153 /* An object monitoring notifications for specific objects. */ 154 155 class SpecificObjectNotifier : public ObjectNotifier 156 { 157 public: 158 virtual long wait_object(notifiable_t *object); 159 160 /* Helper methods. */ 161 162 virtual void notify(notifiable_t *object, notify_flags_t flags, 163 notify_values_t values); 164 }; 165 166 167 168 /* Object-specific notifier resource. */ 169 170 class NotifierResource : public Notifier, public Resource 171 { 172 protected: 173 ObjectNotifier *_notifier; 174 notifiable_t *_object; 175 176 public: 177 explicit NotifierResource(ObjectNotifier *notifier, notifiable_t *object) 178 : _notifier(notifier), _object(object) 179 { 180 } 181 182 explicit NotifierResource() 183 : _notifier(NULL), _object(NULL) 184 { 185 } 186 187 /* Server details. */ 188 189 virtual ipc_server_default_config_type config(); 190 191 virtual void *interface() 192 { return static_cast<Notifier *>(this); } 193 194 /* Notifier methods. */ 195 196 virtual long notify(notify_flags_t flags, notify_values_t values); 197 }; 198 199 200 201 /* Helper functions. */ 202 203 SpecificObjectNotifier *notifier_get_task_notifier(); 204 205 GeneralObjectNotifier *notifier_get_local_notifier(); 206 207 // vim: tabstop=4 expandtab shiftwidth=4