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 #include <vector> 29 30 #include <resource/resource.h> 31 #include <systypes/base.h> 32 33 #include "notifier_interface.h" 34 35 36 37 /* Object-specific notification details. */ 38 39 class ObjectNotificationState 40 { 41 public: 42 /* Synchronisation primitives for state access and notification. */ 43 44 std::mutex lock; 45 std::condition_variable condition; 46 47 /* Pending notifications for monitored objects. */ 48 49 notify_flags_t pending_notifications = 0; 50 notify_values_t pending_values = NOTIFY_VALUES_NULL; 51 52 /* Endpoints associated with monitored objects. */ 53 54 l4_cap_idx_t endpoint = L4_INVALID_CAP; 55 56 bool is_null() { return l4_is_invalid_cap(endpoint); } 57 }; 58 59 60 61 /* Collection types. */ 62 63 typedef std::map<notifiable_t *, ObjectNotificationState> ObjectNotificationStates; 64 typedef std::map<notifiable_t *, std::mutex> ObjectStateLocks; 65 66 typedef std::vector<ipc_server_config_type *> ServerConfigs; 67 68 69 70 /* An object for monitoring object event notifications. */ 71 72 class ObjectNotifier 73 { 74 protected: 75 /* General state access locking. */ 76 77 std::mutex _state_lock; 78 79 /* Object-specific state locking. */ 80 81 ObjectStateLocks _object_locks; 82 83 /* Notification state. */ 84 85 ObjectNotificationStates _state; 86 87 /* Notifier resource details. */ 88 89 ServerConfigs _configs; 90 bool _started = false; 91 l4_cap_idx_t _irq = L4_INVALID_CAP; 92 93 /* Convenience method to access object state. */ 94 95 virtual ObjectNotificationState &object_state(notifiable_t *object, bool create); 96 97 /* Helper methods. */ 98 99 virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object); 100 101 public: 102 virtual ~ObjectNotifier(); 103 104 /* Local operations. */ 105 106 virtual long start(); 107 108 virtual void stop(); 109 110 virtual long subscribe(notifiable_t *object, notify_flags_t flags); 111 112 virtual long unsubscribe(notifiable_t *object); 113 114 virtual long remove_endpoint(notifiable_t *object, l4_cap_idx_t endpoint); 115 116 /* Helper methods. */ 117 118 virtual void notify(notifiable_t *object, notify_flags_t flags, 119 notify_values_t values) = 0; 120 }; 121 122 123 124 /* An object monitoring notifications for a collection of different objects. */ 125 126 class GeneralObjectNotifier : public ObjectNotifier 127 { 128 protected: 129 /* Locking to protect pending notification members and to coordinate access 130 to notifications. */ 131 132 std::mutex _general_lock; 133 134 /* General lock synchronisation. */ 135 136 std::condition_variable _general_condition; 137 138 /* Objects affected by notifications. */ 139 140 std::list<notifiable_t *> _affected; 141 142 /* Helper methods. */ 143 144 virtual bool _retrieve(notifiable_t **object); 145 146 virtual bool _retrieve_for_object(notifiable_t *object); 147 148 public: 149 virtual long wait(notifiable_t **object); 150 151 /* Helper methods. */ 152 153 virtual void notify(notifiable_t *object, notify_flags_t flags, 154 notify_values_t values); 155 }; 156 157 158 159 /* An object monitoring notifications for specific objects. */ 160 161 class SpecificObjectNotifier : public ObjectNotifier 162 { 163 public: 164 virtual long wait_object(notifiable_t *object); 165 166 /* Helper methods. */ 167 168 virtual void notify(notifiable_t *object, notify_flags_t flags, 169 notify_values_t values); 170 }; 171 172 173 174 /* Object-specific notifier resource. */ 175 176 class NotifierResource : public Notifier, public Resource 177 { 178 protected: 179 ObjectNotifier *_notifier; 180 notifiable_t *_object; 181 182 public: 183 explicit NotifierResource(ObjectNotifier *notifier, notifiable_t *object) 184 : _notifier(notifier), _object(object) 185 { 186 } 187 188 explicit NotifierResource() 189 : _notifier(NULL), _object(NULL) 190 { 191 } 192 193 /* Server details. */ 194 195 virtual ipc_server_default_config_type config(); 196 197 virtual void *interface() 198 { return static_cast<Notifier *>(this); } 199 200 /* Notifier methods. */ 201 202 virtual long notify(notify_flags_t flags, notify_values_t values); 203 }; 204 205 206 207 /* Helper functions. */ 208 209 SpecificObjectNotifier *notifier_get_task_notifier(); 210 211 GeneralObjectNotifier *notifier_get_local_notifier(); 212 213 // vim: tabstop=4 expandtab shiftwidth=4