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 92 /* Convenience method to access object state. */ 93 94 virtual ObjectNotificationState &object_state(notifiable_t *object, bool create); 95 96 /* Helper methods. */ 97 98 virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object); 99 100 public: 101 virtual ~ObjectNotifier(); 102 103 /* Local operations. */ 104 105 virtual long start(); 106 107 virtual long subscribe(notifiable_t *object, notify_flags_t flags); 108 109 virtual long unsubscribe(notifiable_t *object); 110 111 virtual long remove_endpoint(notifiable_t *object, l4_cap_idx_t endpoint); 112 113 /* Helper methods. */ 114 115 virtual void notify(notifiable_t *object, notify_flags_t flags, 116 notify_values_t values) = 0; 117 }; 118 119 120 121 /* An object monitoring notifications for a collection of different objects. */ 122 123 class GeneralObjectNotifier : public ObjectNotifier 124 { 125 protected: 126 /* Locking to protect pending notification members and to coordinate access 127 to notifications. */ 128 129 std::mutex _general_lock; 130 131 /* General lock synchronisation. */ 132 133 std::condition_variable _general_condition; 134 135 /* Objects affected by notifications. */ 136 137 std::list<notifiable_t *> _affected; 138 139 /* Helper methods. */ 140 141 virtual bool _retrieve(notifiable_t **object); 142 143 virtual bool _retrieve_for_object(notifiable_t *object); 144 145 public: 146 virtual long wait(notifiable_t **object); 147 148 /* Helper methods. */ 149 150 virtual void notify(notifiable_t *object, notify_flags_t flags, 151 notify_values_t values); 152 }; 153 154 155 156 /* An object monitoring notifications for specific objects. */ 157 158 class SpecificObjectNotifier : public ObjectNotifier 159 { 160 public: 161 virtual long wait_object(notifiable_t *object); 162 163 /* Helper methods. */ 164 165 virtual void notify(notifiable_t *object, notify_flags_t flags, 166 notify_values_t values); 167 }; 168 169 170 171 /* Object-specific notifier resource. */ 172 173 class NotifierResource : public Notifier, public Resource 174 { 175 protected: 176 ObjectNotifier *_notifier; 177 notifiable_t *_object; 178 179 public: 180 explicit NotifierResource(ObjectNotifier *notifier, notifiable_t *object) 181 : _notifier(notifier), _object(object) 182 { 183 } 184 185 explicit NotifierResource() 186 : _notifier(NULL), _object(NULL) 187 { 188 } 189 190 /* Server details. */ 191 192 virtual ipc_server_default_config_type config(); 193 194 virtual void *interface() 195 { return static_cast<Notifier *>(this); } 196 197 /* Notifier methods. */ 198 199 virtual long notify(notify_flags_t flags, notify_values_t values); 200 }; 201 202 203 204 /* Helper functions. */ 205 206 SpecificObjectNotifier *notifier_get_task_notifier(); 207 208 GeneralObjectNotifier *notifier_get_local_notifier(); 209 210 // vim: tabstop=4 expandtab shiftwidth=4