1.1 --- a/libfsclient/include/fsclient/file.h Thu Feb 16 23:36:52 2023 +0100
1.2 +++ b/libfsclient/include/fsclient/file.h Fri Feb 17 18:39:43 2023 +0100
1.3 @@ -41,7 +41,7 @@
1.4
1.5 EXTERN_C_BEGIN
1.6
1.7 -/* File access abstraction. */
1.8 +/* File access abstraction compatible with notifiable_base_t. */
1.9
1.10 typedef struct
1.11 {
1.12 @@ -71,9 +71,9 @@
1.13
1.14 notify_flags_t can_block;
1.15
1.16 - /* Saved notifications. */
1.17 + /* Notification structure. */
1.18
1.19 - notify_flags_t notifications;
1.20 + notifiable_t notifiable;
1.21
1.22 /* Flags indicated when opening the file. */
1.23
1.24 @@ -148,6 +148,9 @@
1.25
1.26 /* Notification functions. */
1.27
1.28 +notifiable_t *file_notifiable(file_t *file);
1.29 +notify_flags_t file_notifications(file_t *file);
1.30 +
1.31 void file_notify_close(file_notifier_t *notifier);
1.32 file_notifier_t *file_notify_local(void);
1.33 file_notifier_t *file_notify_task(void);
2.1 --- a/libfsclient/include/fsclient/notifier.h Thu Feb 16 23:36:52 2023 +0100
2.2 +++ b/libfsclient/include/fsclient/notifier.h Fri Feb 17 18:39:43 2023 +0100
2.3 @@ -1,7 +1,7 @@
2.4 /*
2.5 - * File event notification support.
2.6 + * Generic object event notification support.
2.7 *
2.8 - * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
2.9 + * Copyright (C) 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk>
2.10 *
2.11 * This program is free software; you can redistribute it and/or
2.12 * modify it under the terms of the GNU General Public License as
2.13 @@ -31,9 +31,9 @@
2.14
2.15
2.16
2.17 -/* File-specific notification details. */
2.18 +/* Object-specific notification details. */
2.19
2.20 -class FileNotificationState
2.21 +class ObjectNotificationState
2.22 {
2.23 public:
2.24 /* Synchronisation primitives for state access and notification. */
2.25 @@ -41,11 +41,11 @@
2.26 std::mutex lock;
2.27 std::condition_variable condition;
2.28
2.29 - /* Pending notifications for monitored files. */
2.30 + /* Pending notifications for monitored objects. */
2.31
2.32 notify_flags_t pending = 0;
2.33
2.34 - /* Endpoints associated with monitored files. */
2.35 + /* Endpoints associated with monitored objects. */
2.36
2.37 l4_cap_idx_t endpoint = L4_INVALID_CAP;
2.38
2.39 @@ -56,53 +56,53 @@
2.40
2.41 /* Collection types. */
2.42
2.43 -typedef std::map<file_t *, FileNotificationState> FileNotificationStates;
2.44 -typedef std::map<file_t *, std::mutex> FileStateLocks;
2.45 +typedef std::map<notifiable_t *, ObjectNotificationState> ObjectNotificationStates;
2.46 +typedef std::map<notifiable_t *, std::mutex> ObjectStateLocks;
2.47
2.48
2.49
2.50 -/* An object for monitoring file event notifications. */
2.51 +/* An object for monitoring object event notifications. */
2.52
2.53 -class FileNotifier
2.54 +class ObjectNotifier
2.55 {
2.56 protected:
2.57 /* General state access locking. */
2.58
2.59 std::mutex _state_lock;
2.60
2.61 - /* File-specific state locking. */
2.62 + /* Object-specific state locking. */
2.63
2.64 - FileStateLocks _file_locks;
2.65 + ObjectStateLocks _object_locks;
2.66
2.67 /* Notification state. */
2.68
2.69 - FileNotificationStates _state;
2.70 + ObjectNotificationStates _state;
2.71
2.72 /* Notifier thread details. */
2.73
2.74 l4_cap_idx_t _thread = L4_INVALID_CAP;
2.75 bool _started = false;
2.76
2.77 - /* Convenience method to access file state. */
2.78 + /* Convenience method to access object state. */
2.79
2.80 - virtual FileNotificationState &file_state(file_t *file, bool create);
2.81 + virtual ObjectNotificationState &object_state(notifiable_t *object, bool create);
2.82
2.83 /* Helper methods. */
2.84
2.85 - virtual void _notify(file_t *file, notify_flags_t flags) = 0;
2.86 + virtual void _notify(notifiable_t *object, notify_flags_t flags) = 0;
2.87
2.88 - virtual bool _transfer(FileNotificationState &state, file_t *file);
2.89 + virtual bool _transfer(ObjectNotificationState &state, notifiable_t *object);
2.90
2.91 public:
2.92 - virtual ~FileNotifier();
2.93 + virtual ~ObjectNotifier();
2.94
2.95 /* Local operations. */
2.96
2.97 virtual long start();
2.98
2.99 - virtual long subscribe(file_t *file, notify_flags_t flags);
2.100 + virtual long subscribe(notifiable_t *object, notify_flags_t flags);
2.101
2.102 - virtual long unsubscribe(file_t *file);
2.103 + virtual long unsubscribe(notifiable_t *object);
2.104
2.105 /* Event handling support. */
2.106
2.107 @@ -111,9 +111,9 @@
2.108
2.109
2.110
2.111 -/* An object monitoring notifications for a collection of different files. */
2.112 +/* An object monitoring notifications for a collection of different objects. */
2.113
2.114 -class GeneralFileNotifier : public FileNotifier
2.115 +class GeneralObjectNotifier : public ObjectNotifier
2.116 {
2.117 protected:
2.118 /* Locking to protect pending notification members and to coordinate access
2.119 @@ -125,43 +125,43 @@
2.120
2.121 std::condition_variable _general_condition;
2.122
2.123 - /* Files affected by notifications. */
2.124 + /* Objects affected by notifications. */
2.125
2.126 - std::list<file_t *> _affected;
2.127 + std::list<notifiable_t *> _affected;
2.128
2.129 /* Helper methods. */
2.130
2.131 - virtual void _notify(file_t *file, notify_flags_t flags);
2.132 + virtual void _notify(notifiable_t *object, notify_flags_t flags);
2.133
2.134 - virtual bool _retrieve(file_t **file);
2.135 + virtual bool _retrieve(notifiable_t **object);
2.136
2.137 - virtual bool _retrieve_for_file(file_t *file);
2.138 + virtual bool _retrieve_for_object(notifiable_t *object);
2.139
2.140 public:
2.141 - virtual long wait(file_t **file);
2.142 + virtual long wait(notifiable_t **object);
2.143 };
2.144
2.145
2.146
2.147 -/* An object monitoring notifications for specific files. */
2.148 +/* An object monitoring notifications for specific objects. */
2.149
2.150 -class SpecificFileNotifier : public FileNotifier
2.151 +class SpecificObjectNotifier : public ObjectNotifier
2.152 {
2.153 protected:
2.154 /* Helper methods. */
2.155
2.156 - virtual void _notify(file_t *file, notify_flags_t flags);
2.157 + virtual void _notify(notifiable_t *object, notify_flags_t flags);
2.158
2.159 public:
2.160 - virtual long wait_file(file_t *file);
2.161 + virtual long wait_object(notifiable_t *object);
2.162 };
2.163
2.164
2.165
2.166 /* Helper functions. */
2.167
2.168 -SpecificFileNotifier *notifier_get_task_notifier();
2.169 +SpecificObjectNotifier *notifier_get_task_notifier();
2.170
2.171 -GeneralFileNotifier *notifier_get_local_notifier();
2.172 +GeneralObjectNotifier *notifier_get_local_notifier();
2.173
2.174 // vim: tabstop=4 expandtab shiftwidth=4
3.1 --- a/libfsclient/lib/src/client.cc Thu Feb 16 23:36:52 2023 +0100
3.2 +++ b/libfsclient/lib/src/client.cc Fri Feb 17 18:39:43 2023 +0100
3.3 @@ -150,7 +150,7 @@
3.4
3.5 static int _operation_blocking(file_t *file, int reading)
3.6 {
3.7 - return (file->can_block && !(file->notifications & NOTIFY_PEER_CLOSED) && (
3.8 + return (file->can_block && !(file->notifiable.notifications & NOTIFY_PEER_CLOSED) && (
3.9 (reading && !file_data_available(file)) ||
3.10 (!reading && !file_data_space(file))));
3.11 }
4.1 --- a/libfsclient/lib/src/file.cc Thu Feb 16 23:36:52 2023 +0100
4.2 +++ b/libfsclient/lib/src/file.cc Fri Feb 17 18:39:43 2023 +0100
4.3 @@ -89,9 +89,13 @@
4.4 file->data_current = 0;
4.5 file->object_flags = 0;
4.6 file->can_block = 0;
4.7 - file->notifications = 0;
4.8 file->flags = 0;
4.9 file->error = 0;
4.10 +
4.11 + /* Initialise the notifiable section of the structure. */
4.12 +
4.13 + file->notifiable.notifications = 0;
4.14 + file->notifiable.base = (notifiable_base_t *) file;
4.15 }
4.16
4.17
4.18 @@ -107,7 +111,7 @@
4.19 /* Only unsubscribe after actually closing the file and sending any
4.20 notifications. */
4.21
4.22 - notifier_get_task_notifier()->unsubscribe(file);
4.23 + notifier_get_task_notifier()->unsubscribe(file_notifiable(file));
4.24 }
4.25
4.26 if (file->memory != NULL)
4.27 @@ -607,10 +611,22 @@
4.28
4.29 struct file_notifier
4.30 {
4.31 - FileNotifier *obj;
4.32 + ObjectNotifier *obj;
4.33 };
4.34
4.35 +/* Conversion to the generic notification types. */
4.36
4.37 +notifiable_t *file_notifiable(file_t *file)
4.38 +{
4.39 + return &file->notifiable;
4.40 +}
4.41 +
4.42 +/* Return the notification flags for a file. */
4.43 +
4.44 +notify_flags_t file_notifications(file_t *file)
4.45 +{
4.46 + return file->notifiable.notifications;
4.47 +}
4.48
4.49 /* Close a notifier object. */
4.50
4.51 @@ -644,26 +660,26 @@
4.52
4.53 long file_notify_subscribe(file_t *file, notify_flags_t flags, file_notifier_t *notifier)
4.54 {
4.55 - return notifier->obj->subscribe(file, flags);
4.56 + return notifier->obj->subscribe(file_notifiable(file), flags);
4.57 }
4.58
4.59 /* Unsubscribe from notification events on a file. */
4.60
4.61 long file_notify_unsubscribe(file_t *file, file_notifier_t *notifier)
4.62 {
4.63 - return notifier->obj->unsubscribe(file);
4.64 + return notifier->obj->unsubscribe(file_notifiable(file));
4.65 }
4.66
4.67 /* Wait for a notification event on a file. */
4.68
4.69 long file_notify_wait_file(file_t *file, file_notifier_t *notifier)
4.70 {
4.71 - SpecificFileNotifier *specific_notifier = dynamic_cast<SpecificFileNotifier *>(notifier->obj);
4.72 - long err = specific_notifier->wait_file(file);
4.73 + SpecificObjectNotifier *specific_notifier = dynamic_cast<SpecificObjectNotifier *>(notifier->obj);
4.74 + long err = specific_notifier->wait_object(file_notifiable(file));
4.75
4.76 /* Unsubscribe if a closure notification has been received. */
4.77
4.78 - if (!err && (file->notifications & NOTIFY_PEER_CLOSED))
4.79 + if (!err && (file->notifiable.notifications & NOTIFY_PEER_CLOSED))
4.80 file_notify_unsubscribe(file, notifier);
4.81
4.82 return err;
4.83 @@ -673,12 +689,15 @@
4.84
4.85 long file_notify_wait_files(file_t **file, file_notifier_t *notifier)
4.86 {
4.87 - GeneralFileNotifier *general_notifier = dynamic_cast<GeneralFileNotifier *>(notifier->obj);
4.88 - long err = general_notifier->wait(file);
4.89 + GeneralObjectNotifier *general_notifier = dynamic_cast<GeneralObjectNotifier *>(notifier->obj);
4.90 + notifiable_t *notifiable;
4.91 + long err = general_notifier->wait(¬ifiable);
4.92 +
4.93 + *file = (file_t *) notifiable->base;
4.94
4.95 /* Unsubscribe if a closure notification has been received. */
4.96
4.97 - if (!err && ((*file)->notifications & NOTIFY_PEER_CLOSED))
4.98 + if (!err && ((*file)->notifiable.notifications & NOTIFY_PEER_CLOSED))
4.99 file_notify_unsubscribe(*file, notifier);
4.100
4.101 return err;
5.1 --- a/libfsclient/lib/src/notifier.cc Thu Feb 16 23:36:52 2023 +0100
5.2 +++ b/libfsclient/lib/src/notifier.cc Fri Feb 17 18:39:43 2023 +0100
5.3 @@ -1,7 +1,7 @@
5.4 /*
5.5 - * File event notification support.
5.6 + * Generic object event notification support.
5.7 *
5.8 - * Copyright (C) 2021, 2022 Paul Boddie <paul@boddie.org.uk>
5.9 + * Copyright (C) 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk>
5.10 *
5.11 * This program is free software; you can redistribute it and/or
5.12 * modify it under the terms of the GNU General Public License as
5.13 @@ -35,7 +35,7 @@
5.14
5.15 /* Null notification state. */
5.16
5.17 -static FileNotificationState _null_state;
5.18 +static ObjectNotificationState _null_state;
5.19
5.20
5.21
5.22 @@ -45,13 +45,13 @@
5.23
5.24 /* Per-task storage for specific waiting operations. */
5.25
5.26 -static SpecificFileNotifier *_notifier = NULL;
5.27 +static SpecificObjectNotifier *_notifier = NULL;
5.28
5.29
5.30
5.31 -/* Return the per-task notifier for file-specific waiting operations. */
5.32 +/* Return the per-task notifier for object-specific waiting operations. */
5.33
5.34 -SpecificFileNotifier *notifier_get_task_notifier()
5.35 +SpecificObjectNotifier *notifier_get_task_notifier()
5.36 {
5.37 std::lock_guard<std::mutex> guard(_lock);
5.38
5.39 @@ -59,18 +59,18 @@
5.40
5.41 if (_notifier == NULL)
5.42 {
5.43 - _notifier = new SpecificFileNotifier;
5.44 + _notifier = new SpecificObjectNotifier;
5.45 _notifier->start();
5.46 }
5.47
5.48 return _notifier;
5.49 }
5.50
5.51 -/* Return a local notifier for general file waiting operations. */
5.52 +/* Return a local notifier for general object waiting operations. */
5.53
5.54 -GeneralFileNotifier *notifier_get_local_notifier()
5.55 +GeneralObjectNotifier *notifier_get_local_notifier()
5.56 {
5.57 - GeneralFileNotifier *notifier = new GeneralFileNotifier;
5.58 + GeneralObjectNotifier *notifier = new GeneralObjectNotifier;
5.59
5.60 notifier->start();
5.61 return notifier;
5.62 @@ -82,7 +82,7 @@
5.63
5.64 static void *notifier_mainloop(void *data)
5.65 {
5.66 - FileNotifier *notifier = reinterpret_cast<FileNotifier *>(data);
5.67 + ObjectNotifier *notifier = reinterpret_cast<ObjectNotifier *>(data);
5.68
5.69 notifier->mainloop();
5.70 return 0;
5.71 @@ -92,13 +92,13 @@
5.72
5.73 /* Virtual destructor required for base class instance reference deletion. */
5.74
5.75 -FileNotifier::~FileNotifier()
5.76 +ObjectNotifier::~ObjectNotifier()
5.77 {
5.78 }
5.79
5.80 /* Listen for notifications. */
5.81
5.82 -void FileNotifier::mainloop()
5.83 +void ObjectNotifier::mainloop()
5.84 {
5.85 ipc_message_t msg;
5.86 l4_umword_t label;
5.87 @@ -116,9 +116,9 @@
5.88 if (l4_ipc_error(msg.tag, l4_utcb()))
5.89 continue;
5.90
5.91 - /* Interpret gate labels as file objects. */
5.92 + /* Interpret gate labels as notifiable objects. */
5.93
5.94 - file_t *file = (file_t *) label;
5.95 + notifiable_t *object = (notifiable_t *) label;
5.96
5.97 /* Obtain message details. */
5.98
5.99 @@ -133,7 +133,7 @@
5.100
5.101 /* Register the notification. */
5.102
5.103 - _notify(file, flags);
5.104 + _notify(object, flags);
5.105 }
5.106
5.107 ipc_message_free(&msg);
5.108 @@ -141,7 +141,7 @@
5.109
5.110 /* Start listening for notifications. */
5.111
5.112 -long FileNotifier::start()
5.113 +long ObjectNotifier::start()
5.114 {
5.115 if (_started)
5.116 return L4_EOK;
5.117 @@ -165,17 +165,17 @@
5.118
5.119
5.120
5.121 -/* Return a notification state object for the given file or a null object if no
5.122 - record existed for the file. */
5.123 +/* Return notification state for the given object or null state if no record
5.124 + existed for the object. */
5.125
5.126 -FileNotificationState &FileNotifier::file_state(file_t *file, bool create)
5.127 +ObjectNotificationState &ObjectNotifier::object_state(notifiable_t *object, bool create)
5.128 {
5.129 - FileNotificationStates::iterator it = _state.find(file);
5.130 + ObjectNotificationStates::iterator it = _state.find(object);
5.131
5.132 if (it == _state.end())
5.133 {
5.134 if (create)
5.135 - return _state[file];
5.136 + return _state[object];
5.137 else
5.138 return _null_state;
5.139 }
5.140 @@ -183,22 +183,22 @@
5.141 return it->second;
5.142 }
5.143
5.144 -/* Subscribe to notification events on a file. */
5.145 +/* Subscribe to notification events on an object. */
5.146
5.147 -long FileNotifier::subscribe(file_t *file, notify_flags_t flags)
5.148 +long ObjectNotifier::subscribe(notifiable_t *object, notify_flags_t flags)
5.149 {
5.150 /* Acquire the lock for state lookup. */
5.151
5.152 std::unique_lock<std::mutex> state_guard(_state_lock);
5.153
5.154 - FileNotificationState &state = file_state(file, true);
5.155 + ObjectNotificationState &state = object_state(object, true);
5.156 long err;
5.157
5.158 /* Create a notification endpoint, if necessary. */
5.159
5.160 if (state.is_null())
5.161 {
5.162 - err = ipc_server_new_for_thread(&state.endpoint, file, _thread);
5.163 + err = ipc_server_new_for_thread(&state.endpoint, object, _thread);
5.164
5.165 if (err)
5.166 return err;
5.167 @@ -206,59 +206,59 @@
5.168
5.169 /* Subscribe, sending the notification endpoint. */
5.170
5.171 - client_Notification notify(file->ref);
5.172 + client_Notification notify(object->base->ref);
5.173
5.174 err = notify.subscribe(state.endpoint, flags);
5.175
5.176 if (err)
5.177 {
5.178 ipc_cap_free_um(state.endpoint);
5.179 - _state.erase(file);
5.180 + _state.erase(object);
5.181 return err;
5.182 }
5.183
5.184 return L4_EOK;
5.185 }
5.186
5.187 -/* Unsubscribe from notification events on a file. */
5.188 +/* Unsubscribe from notification events on an object. */
5.189
5.190 -long FileNotifier::unsubscribe(file_t *file)
5.191 +long ObjectNotifier::unsubscribe(notifiable_t *object)
5.192 {
5.193 /* Acquire the lock for state lookup. */
5.194
5.195 std::unique_lock<std::mutex> state_guard(_state_lock);
5.196
5.197 - FileNotificationState &state = file_state(file, false);
5.198 + ObjectNotificationState &state = object_state(object, false);
5.199
5.200 if (state.is_null())
5.201 return -L4_EINVAL;
5.202
5.203 /* Unsubscribe via the notification interface. */
5.204
5.205 - client_Notification notify(file->ref);
5.206 + client_Notification notify(object->base->ref);
5.207
5.208 notify.unsubscribe();
5.209
5.210 ipc_cap_free_um(state.endpoint);
5.211
5.212 - _state.erase(file);
5.213 + _state.erase(object);
5.214
5.215 - /* Remove the lock for updating file state. */
5.216 + /* Remove the lock for updating object state. */
5.217
5.218 - _file_locks.erase(file);
5.219 + _object_locks.erase(object);
5.220
5.221 return L4_EOK;
5.222 }
5.223
5.224
5.225
5.226 -/* Handle a notification event for a file. Ideally, this would be invoked by the
5.227 - generic server dispatch mechanism, with the gate label being interpreted and
5.228 - provided as the first parameter. */
5.229 +/* Handle a notification event for an object. Ideally, this would be invoked by
5.230 + the generic server dispatch mechanism, with the gate label being interpreted
5.231 + and provided as the first parameter. */
5.232
5.233 -void GeneralFileNotifier::_notify(file_t *file, notify_flags_t flags)
5.234 +void GeneralObjectNotifier::_notify(notifiable_t *object, notify_flags_t flags)
5.235 {
5.236 - /* Enter critical section for the notifier (affecting all files). */
5.237 + /* Enter critical section for the notifier (affecting all objects). */
5.238
5.239 std::unique_lock<std::mutex> general_guard(_general_lock);
5.240
5.241 @@ -266,14 +266,14 @@
5.242
5.243 std::unique_lock<std::mutex> state_guard(_state_lock);
5.244
5.245 - FileNotificationState &state = file_state(file, false);
5.246 + ObjectNotificationState &state = object_state(object, false);
5.247
5.248 if (state.is_null())
5.249 return;
5.250
5.251 - /* Acquire the lock for the file state itself. */
5.252 + /* Acquire the lock for the object state itself. */
5.253
5.254 - std::unique_lock<std::mutex> file_guard(state.lock);
5.255 + std::unique_lock<std::mutex> object_guard(state.lock);
5.256
5.257 /* Record flags and return previous flags. */
5.258
5.259 @@ -281,30 +281,30 @@
5.260
5.261 state.pending |= flags;
5.262
5.263 - /* Add a file queue entry for any files without previous notifications. */
5.264 + /* Add an object queue entry for any objects without previous notifications. */
5.265
5.266 if (!recorded)
5.267 - _affected.push_back(file);
5.268 + _affected.push_back(object);
5.269
5.270 /* Notify any waiting caller. */
5.271
5.272 _general_condition.notify_one();
5.273 }
5.274
5.275 -void SpecificFileNotifier::_notify(file_t *file, notify_flags_t flags)
5.276 +void SpecificObjectNotifier::_notify(notifiable_t *object, notify_flags_t flags)
5.277 {
5.278 /* Acquire the lock for state lookup. */
5.279
5.280 std::unique_lock<std::mutex> state_guard(_state_lock);
5.281
5.282 - FileNotificationState &state = file_state(file, false);
5.283 + ObjectNotificationState &state = object_state(object, false);
5.284
5.285 if (state.is_null())
5.286 return;
5.287
5.288 - /* Acquire the lock for the file state itself. */
5.289 + /* Acquire the lock for the object state itself. */
5.290
5.291 - std::unique_lock<std::mutex> file_guard(state.lock);
5.292 + std::unique_lock<std::mutex> object_guard(state.lock);
5.293
5.294 state.pending |= flags;
5.295
5.296 @@ -315,16 +315,16 @@
5.297
5.298
5.299
5.300 -/* Transfer pending notifications to the given file. This must be called with a
5.301 - lock acquired on the file notification state. */
5.302 +/* Transfer pending notifications to the given object. This must be called with
5.303 + a lock acquired on the object notification state. */
5.304
5.305 -bool FileNotifier::_transfer(FileNotificationState &state, file_t *file)
5.306 +bool ObjectNotifier::_transfer(ObjectNotificationState &state, notifiable_t *object)
5.307 {
5.308 notify_flags_t recorded = state.pending;
5.309
5.310 if (recorded)
5.311 {
5.312 - file->notifications = recorded;
5.313 + object->notifications = recorded;
5.314 state.pending = 0;
5.315 return true;
5.316 }
5.317 @@ -334,41 +334,41 @@
5.318
5.319
5.320
5.321 -/* Obtain file state and transfer notifications. */
5.322 +/* Obtain object state and transfer notifications. */
5.323
5.324 -bool GeneralFileNotifier::_retrieve_for_file(file_t *file)
5.325 +bool GeneralObjectNotifier::_retrieve_for_object(notifiable_t *object)
5.326 {
5.327 /* Acquire the lock for state lookup. */
5.328
5.329 std::unique_lock<std::mutex> state_guard(_state_lock);
5.330
5.331 - FileNotificationState &state = file_state(file, false);
5.332 + ObjectNotificationState &state = object_state(object, false);
5.333
5.334 if (state.is_null())
5.335 return false;
5.336
5.337 - /* Acquire the lock for the file state itself, then release the state lock. */
5.338 + /* Acquire the lock for the object state itself, then release the state lock. */
5.339
5.340 - std::unique_lock<std::mutex> file_guard(state.lock);
5.341 + std::unique_lock<std::mutex> object_guard(state.lock);
5.342
5.343 state_guard.unlock();
5.344
5.345 /* Call generic method to transfer notifications, if possible. */
5.346
5.347 - return _transfer(state, file);
5.348 + return _transfer(state, object);
5.349 }
5.350
5.351 -/* Obtain queued files until one is found that still has events recorded for it.
5.352 - This must be called with the notifier's general lock acquired. */
5.353 +/* Obtain queued objects until one is found that still has events recorded for
5.354 + it. This must be called with the notifier's general lock acquired. */
5.355
5.356 -bool GeneralFileNotifier::_retrieve(file_t **file)
5.357 +bool GeneralObjectNotifier::_retrieve(notifiable_t **object)
5.358 {
5.359 while (!_affected.empty())
5.360 {
5.361 - *file = _affected.front();
5.362 + *object = _affected.front();
5.363 _affected.pop_front();
5.364
5.365 - if (_retrieve_for_file(*file))
5.366 + if (_retrieve_for_object(*object))
5.367 return true;
5.368 }
5.369
5.370 @@ -377,17 +377,17 @@
5.371
5.372
5.373
5.374 -/* Wait for notification events on files. */
5.375 +/* Wait for notification events on objects. */
5.376
5.377 -long GeneralFileNotifier::wait(file_t **file)
5.378 +long GeneralObjectNotifier::wait(notifiable_t **object)
5.379 {
5.380 std::unique_lock<std::mutex> general_guard(_general_lock);
5.381
5.382 while (1)
5.383 {
5.384 - /* With pending notifications, update the first file and exit. */
5.385 + /* With pending notifications, update the first object and exit. */
5.386
5.387 - if (_retrieve(file))
5.388 + if (_retrieve(object))
5.389 break;
5.390
5.391 /* Otherwise, wait for notifications. */
5.392 @@ -398,35 +398,35 @@
5.393 return L4_EOK;
5.394 }
5.395
5.396 -/* Wait for notifications from a single file. */
5.397 +/* Wait for notifications from a single object. */
5.398
5.399 -long SpecificFileNotifier::wait_file(file_t *file)
5.400 +long SpecificObjectNotifier::wait_object(notifiable_t *object)
5.401 {
5.402 - /* Acquire the lock for reading file state. */
5.403 + /* Acquire the lock for reading object state. */
5.404
5.405 std::unique_lock<std::mutex> state_guard(_state_lock);
5.406
5.407 - FileNotificationState &state = file_state(file, false);
5.408 + ObjectNotificationState &state = object_state(object, false);
5.409
5.410 if (state.is_null())
5.411 return -L4_EINVAL;
5.412
5.413 - /* Acquire the lock for the file state itself, then release the state lock. */
5.414 + /* Acquire the lock for the object state itself, then release the state lock. */
5.415
5.416 - std::unique_lock<std::mutex> file_guard(state.lock);
5.417 + std::unique_lock<std::mutex> object_guard(state.lock);
5.418
5.419 state_guard.unlock();
5.420
5.421 while (1)
5.422 {
5.423 - /* With pending notifications, update the file and exit. */
5.424 + /* With pending notifications, update the object and exit. */
5.425
5.426 - if (_transfer(state, file))
5.427 + if (_transfer(state, object))
5.428 break;
5.429
5.430 /* Otherwise, wait for notifications. */
5.431
5.432 - state.condition.wait(file_guard);
5.433 + state.condition.wait(object_guard);
5.434 }
5.435
5.436 return L4_EOK;
6.1 --- a/libsystypes/include/systypes/base.h Thu Feb 16 23:36:52 2023 +0100
6.2 +++ b/libsystypes/include/systypes/base.h Fri Feb 17 18:39:43 2023 +0100
6.3 @@ -1,7 +1,7 @@
6.4 /*
6.5 * Base types used by various other types.
6.6 *
6.7 - * Copyright (C) 2019, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
6.8 + * Copyright (C) 2019, 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk>
6.9 *
6.10 * This program is free software; you can redistribute it and/or
6.11 * modify it under the terms of the GNU General Public License as
6.12 @@ -49,12 +49,28 @@
6.13
6.14 enum notify_flags
6.15 {
6.16 - NOTIFY_CONTENT_AVAILABLE = 1, /* reading files and pipes */
6.17 - NOTIFY_SPACE_AVAILABLE = 2, /* writing pipes */
6.18 - NOTIFY_PEER_CLOSED = 4, /* closing files and pipes */
6.19 - NOTIFY_FILE_OPENED = 8, /* opening files in directories */
6.20 + NOTIFY_CONTENT_AVAILABLE = 0x001, /* reading files and pipes */
6.21 + NOTIFY_SPACE_AVAILABLE = 0x002, /* writing pipes */
6.22 + NOTIFY_PEER_CLOSED = 0x004, /* closing files and pipes */
6.23 + NOTIFY_FILE_OPENED = 0x008, /* opening files in directories */
6.24 + NOTIFY_TASK_SIGNAL = 0x100, /* signal from task */
6.25 };
6.26
6.27 +/* Notifiable object types. */
6.28 +
6.29 +typedef struct
6.30 +{
6.31 + l4_cap_idx_t ref;
6.32 +
6.33 +} notifiable_base_t;
6.34 +
6.35 +typedef struct
6.36 +{
6.37 + notifiable_base_t *base; /* access to the specific object */
6.38 + notify_flags_t notifications;
6.39 +
6.40 +} notifiable_t;
6.41 +
6.42 /* Filesystem object properties. */
6.43
6.44 typedef unsigned long object_flags_t;
7.1 --- a/libsystypes/include/systypes/format.h Thu Feb 16 23:36:52 2023 +0100
7.2 +++ b/libsystypes/include/systypes/format.h Fri Feb 17 18:39:43 2023 +0100
7.3 @@ -1,7 +1,7 @@
7.4 /*
7.5 * Format specifiers for output.
7.6 *
7.7 - * Copyright (C) 2022 Paul Boddie <paul@boddie.org.uk>
7.8 + * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk>
7.9 *
7.10 * This program is free software; you can redistribute it and/or
7.11 * modify it under the terms of the GNU General Public License as
7.12 @@ -40,6 +40,7 @@
7.13 /* See: systypes/base.h */
7.14
7.15 #define pFMToffset "ll"
7.16 +#define pFMTnotify_flags "ll"
7.17
7.18 /* Alternative for size_t or ssize_t (%z). */
7.19
8.1 --- a/tests/dstest_file_client.cc Thu Feb 16 23:36:52 2023 +0100
8.2 +++ b/tests/dstest_file_client.cc Fri Feb 17 18:39:43 2023 +0100
8.3 @@ -1,7 +1,7 @@
8.4 /*
8.5 * Test file operations.
8.6 *
8.7 - * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
8.8 + * Copyright (C) 2020, 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk>
8.9 *
8.10 * This program is free software; you can redistribute it and/or
8.11 * modify it under the terms of the GNU General Public License as
8.12 @@ -97,8 +97,8 @@
8.13 }
8.14
8.15 printf("File %s notified with conditions:%s%s\n", creator ? "creator" : "follower",
8.16 - file->notifications & NOTIFY_PEER_CLOSED ? " closed" : "",
8.17 - file->notifications & NOTIFY_CONTENT_AVAILABLE ? " content" : "");
8.18 + file_notifications(file) & NOTIFY_PEER_CLOSED ? " closed" : "",
8.19 + file_notifications(file) & NOTIFY_CONTENT_AVAILABLE ? " content" : "");
8.20
8.21 /* Attempt to read. */
8.22
8.23 @@ -120,7 +120,7 @@
8.24 /* Without any more content, a peer closed event should terminate reading
8.25 from the file. */
8.26
8.27 - if (file->notifications & NOTIFY_PEER_CLOSED)
8.28 + if (file_notifications(file) & NOTIFY_PEER_CLOSED)
8.29 break;
8.30
8.31 /* Otherwise, write some data to the file for the other party. */
9.1 --- a/tests/dstest_file_monitor.cc Thu Feb 16 23:36:52 2023 +0100
9.2 +++ b/tests/dstest_file_monitor.cc Fri Feb 17 18:39:43 2023 +0100
9.3 @@ -1,7 +1,7 @@
9.4 /*
9.5 * Test directory monitoring operations.
9.6 *
9.7 - * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
9.8 + * Copyright (C) 2020, 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk>
9.9 *
9.10 * This program is free software; you can redistribute it and/or
9.11 * modify it under the terms of the GNU General Public License as
9.12 @@ -87,7 +87,7 @@
9.13 return;
9.14 }
9.15
9.16 - printf("Notified with conditions:%s\n", directory->notifications & NOTIFY_FILE_OPENED ? " file opened" : "");
9.17 + printf("Notified with conditions:%s\n", file_notifications(directory) & NOTIFY_FILE_OPENED ? " file opened" : "");
9.18 }
9.19
9.20 printf("Notified for all expected files: %s\n", expected ? "False" : "True");
10.1 --- a/tests/dstest_pipe_client.cc Thu Feb 16 23:36:52 2023 +0100
10.2 +++ b/tests/dstest_pipe_client.cc Fri Feb 17 18:39:43 2023 +0100
10.3 @@ -1,7 +1,7 @@
10.4 /*
10.5 * Test pipe operations.
10.6 *
10.7 - * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
10.8 + * Copyright (C) 2020, 2021, 2022, 2023 Paul Boddie <paul@boddie.org.uk>
10.9 *
10.10 * This program is free software; you can redistribute it and/or
10.11 * modify it under the terms of the GNU General Public License as
10.12 @@ -124,8 +124,8 @@
10.13
10.14 int p = reader == reader1 ? 0 : 1;
10.15
10.16 - printf("Pipe #%d notified with conditions:%s%s\n", p + 1, reader->notifications & NOTIFY_PEER_CLOSED ? " closed" : "",
10.17 - reader->notifications & NOTIFY_CONTENT_AVAILABLE ? " content" : "");
10.18 + printf("Pipe #%d notified with conditions:%s%s\n", p + 1, file_notifications(reader) & NOTIFY_PEER_CLOSED ? " closed" : "",
10.19 + file_notifications(reader) & NOTIFY_CONTENT_AVAILABLE ? " content" : "");
10.20
10.21 nread = client_read(reader, buffer, TO_TRANSFER);
10.22
10.23 @@ -140,7 +140,7 @@
10.24 /* Without any more content, a peer closed event should terminate reading
10.25 from the pipe. */
10.26
10.27 - if (reader->notifications & NOTIFY_PEER_CLOSED)
10.28 + if (file_notifications(reader) & NOTIFY_PEER_CLOSED)
10.29 {
10.30 active--;
10.31 if (!active)