1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libfsserver/include/fsserver/notification.h Sun Jul 11 23:21:08 2021 +0200
1.3 @@ -0,0 +1,60 @@
1.4 +/*
1.5 + * Notification support.
1.6 + *
1.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#pragma once
1.26 +
1.27 +#include <set>
1.28 +
1.29 +#include <systypes/base.h>
1.30 +
1.31 +
1.32 +
1.33 +/* Notification support, allowing pipe or file users to receive events due to
1.34 + activity on those objects. */
1.35 +
1.36 +class NotificationSupport
1.37 +{
1.38 +protected:
1.39 + /* Endpoint count. */
1.40 +
1.41 + unsigned int _max_endpoints;
1.42 +
1.43 + /* Notification endpoints and flags, set up at initialisation for the
1.44 + appropriate number of endpoints. */
1.45 +
1.46 + std::set<l4_cap_idx_t> *_notifiers;
1.47 + notify_flags_t *_flags, *_deferred;
1.48 +
1.49 + virtual void release_notifiers();
1.50 +
1.51 +public:
1.52 + explicit NotificationSupport(unsigned int endpoints);
1.53 +
1.54 + virtual ~NotificationSupport();
1.55 +
1.56 + virtual void notify(unsigned int endpoint, notify_flags_t flags, l4_cap_idx_t source=L4_INVALID_CAP);
1.57 +
1.58 + virtual void subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags);
1.59 +
1.60 + virtual void unsubscribe(unsigned int endpoint, l4_cap_idx_t notifier);
1.61 +};
1.62 +
1.63 +// vim: tabstop=4 expandtab shiftwidth=4
2.1 --- a/libfsserver/include/fsserver/pipe_paging.h Sun Jul 11 23:11:39 2021 +0200
2.2 +++ b/libfsserver/include/fsserver/pipe_paging.h Sun Jul 11 23:21:08 2021 +0200
2.3 @@ -23,6 +23,7 @@
2.4
2.5 #include <set>
2.6
2.7 +#include <fsserver/notification.h>
2.8 #include <fsserver/page_mapper.h>
2.9 #include <fsserver/pages.h>
2.10 #include <fsserver/pipe_accessor.h>
2.11 @@ -32,7 +33,7 @@
2.12 /* Pipe paging support, maintaining the sequence of active regions or sections
2.13 in a pipe. */
2.14
2.15 -class PipePaging
2.16 +class PipePaging : public NotificationSupport
2.17 {
2.18 protected:
2.19 Memory *_memory;
2.20 @@ -56,11 +57,6 @@
2.21
2.22 unsigned int _endpoints = 2;
2.23
2.24 - /* Notification endpoints. */
2.25 -
2.26 - std::set<l4_cap_idx_t> _notifiers[2];
2.27 - notify_flags_t _flags[2], _deferred[2];
2.28 -
2.29 /* Common functionality. */
2.30
2.31 virtual void discard_region(unsigned int i);
2.32 @@ -73,7 +69,7 @@
2.33 virtual offset_t region_size()
2.34 { return _size; }
2.35
2.36 - /* Notification support. */
2.37 + /* Notification support customised for pipes. */
2.38
2.39 virtual void notify(bool writing, notify_flags_t flags);
2.40
3.1 --- a/libfsserver/lib/Makefile Sun Jul 11 23:11:39 2021 +0200
3.2 +++ b/libfsserver/lib/Makefile Sun Jul 11 23:21:08 2021 +0200
3.3 @@ -52,6 +52,7 @@
3.4 files/test_file_accessor.cc \
3.5 files/test_file_opener.cc \
3.6 generic/accessor.cc \
3.7 + generic/notification.cc \
3.8 generic/pager.cc \
3.9 generic/resource_server.cc \
3.10 generic/simple_pager.cc \
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/libfsserver/lib/generic/notification.cc Sun Jul 11 23:21:08 2021 +0200
4.3 @@ -0,0 +1,129 @@
4.4 +/*
4.5 + * Notification support.
4.6 + *
4.7 + * Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
4.8 + *
4.9 + * This program is free software; you can redistribute it and/or
4.10 + * modify it under the terms of the GNU General Public License as
4.11 + * published by the Free Software Foundation; either version 2 of
4.12 + * the License, or (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program; if not, write to the Free Software
4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
4.22 + * Boston, MA 02110-1301, USA
4.23 + */
4.24 +
4.25 +#include <ipc/cap_alloc.h>
4.26 +
4.27 +#include "notification.h"
4.28 +#include "notifier_client.h"
4.29 +
4.30 +
4.31 +
4.32 +/* Initialise endpoints and flags for notifications. */
4.33 +
4.34 +NotificationSupport::NotificationSupport(unsigned int endpoints)
4.35 +: _max_endpoints(endpoints)
4.36 +{
4.37 + _notifiers = new std::set<l4_cap_idx_t>[endpoints];
4.38 + _flags = new notify_flags_t[endpoints];
4.39 + _deferred = new notify_flags_t[endpoints];
4.40 +
4.41 + for (unsigned int endpoint = 0; endpoint < _max_endpoints; endpoint++)
4.42 + {
4.43 + _flags[endpoint] = 0;
4.44 + _deferred[endpoint] = 0;
4.45 + }
4.46 +}
4.47 +
4.48 +NotificationSupport::~NotificationSupport()
4.49 +{
4.50 + delete _notifiers;
4.51 + delete _flags;
4.52 + delete _deferred;
4.53 +}
4.54 +
4.55 +/* Subscribe to an endpoint's notifications using a notification endpoint. */
4.56 +
4.57 +void NotificationSupport::subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags)
4.58 +{
4.59 + _notifiers[endpoint].insert(notifier);
4.60 + _flags[endpoint] = flags;
4.61 +
4.62 + /* Send deferred conditions held from before subscription occurred. */
4.63 +
4.64 + if (_deferred[endpoint])
4.65 + {
4.66 + notify(endpoint, _deferred[endpoint]);
4.67 + _deferred[endpoint] = 0;
4.68 + }
4.69 +}
4.70 +
4.71 +/* Unsubscribe from an endpoint's notifications. */
4.72 +
4.73 +void NotificationSupport::unsubscribe(unsigned int endpoint, l4_cap_idx_t notifier)
4.74 +{
4.75 + std::set<l4_cap_idx_t>::iterator it = _notifiers[endpoint].find(notifier);
4.76 +
4.77 + if (it != _notifiers[endpoint].end())
4.78 + {
4.79 + _notifiers[endpoint].erase(it);
4.80 + _flags[endpoint] = 0;
4.81 + _deferred[endpoint] = 0;
4.82 + ipc_cap_free_um(notifier);
4.83 + }
4.84 +}
4.85 +
4.86 +/* Notify the other endpoint. */
4.87 +
4.88 +void NotificationSupport::notify(unsigned int endpoint, notify_flags_t flags, l4_cap_idx_t source)
4.89 +{
4.90 + /* Notify the endpoint or hold any notification for potential future
4.91 + subscription. */
4.92 +
4.93 + if (!_notifiers[endpoint].empty())
4.94 + {
4.95 + if (flags & _flags[endpoint])
4.96 + {
4.97 + std::set<l4_cap_idx_t>::iterator it;
4.98 +
4.99 + for (it = _notifiers[endpoint].begin(); it != _notifiers[endpoint].end(); it++)
4.100 + {
4.101 + /* Avoid notifying the source of the notification if it is
4.102 + present in the list. */
4.103 +
4.104 + if (l4_is_valid_cap(source) && (*it == source))
4.105 + continue;
4.106 +
4.107 + client_Notifier notifier(*it);
4.108 +
4.109 + notifier.notify(flags & _flags[endpoint]);
4.110 + }
4.111 + }
4.112 + }
4.113 + else
4.114 + _deferred[endpoint] = flags;
4.115 +}
4.116 +
4.117 +/* Release notifiers for each endpoint. */
4.118 +
4.119 +void NotificationSupport::release_notifiers()
4.120 +{
4.121 + for (unsigned int endpoint = 0; endpoint < _max_endpoints; endpoint++)
4.122 + {
4.123 + std::set<l4_cap_idx_t>::iterator it;
4.124 +
4.125 + for (it = _notifiers[endpoint].begin(); it != _notifiers[endpoint].end(); it++)
4.126 + ipc_cap_free_um(*it);
4.127 +
4.128 + _notifiers[endpoint].clear();
4.129 + }
4.130 +}
4.131 +
4.132 +// vim: tabstop=4 expandtab shiftwidth=4
5.1 --- a/libfsserver/lib/pipes/pipe_paging.cc Sun Jul 11 23:11:39 2021 +0200
5.2 +++ b/libfsserver/lib/pipes/pipe_paging.cc Sun Jul 11 23:21:08 2021 +0200
5.3 @@ -19,7 +19,6 @@
5.4 * Boston, MA 02110-1301, USA
5.5 */
5.6
5.7 -#include <ipc/cap_alloc.h>
5.8 #include <mem/memory_preallocated.h>
5.9
5.10 #include "page_queue_partitioned.h"
5.11 @@ -30,7 +29,7 @@
5.12
5.13
5.14 PipePaging::PipePaging(Memory *memory, offset_t size)
5.15 -: _memory(NULL), _size(size)
5.16 +: NotificationSupport(2), _memory(NULL), _size(size)
5.17 {
5.18 /* Reserve space for two pipe regions. */
5.19
5.20 @@ -42,49 +41,20 @@
5.21
5.22 for (unsigned int i = 0; i < 2; i++)
5.23 _regions[i] = NULL;
5.24 -
5.25 - /* Initialise endpoints and flags for notifications. */
5.26 -
5.27 - for (unsigned int i = 0; i < 2; i++)
5.28 - {
5.29 - _flags[i] = 0;
5.30 - _deferred[i] = 0;
5.31 - }
5.32 }
5.33
5.34 -/* Subscribe to an endpoint's notifications using a notification endpoint. */
5.35 +/* Subscribe to an endpoint's notifications using a notifier object. */
5.36
5.37 void PipePaging::subscribe(bool writing, l4_cap_idx_t notifier, notify_flags_t flags)
5.38 {
5.39 - int i = writing ? 1 : 0;
5.40 -
5.41 - _notifiers[i].insert(notifier);
5.42 - _flags[i] = flags;
5.43 -
5.44 - /* Send deferred conditions on behalf of the other endpoint held before
5.45 - subscription occurred. */
5.46 -
5.47 - if (_deferred[i])
5.48 - {
5.49 - notify(!writing, _deferred[i]);
5.50 - _deferred[i] = 0;
5.51 - }
5.52 + NotificationSupport::subscribe(writing ? 1 : 0, notifier, flags);
5.53 }
5.54
5.55 /* Unsubscribe from an endpoint's notifications. */
5.56
5.57 void PipePaging::unsubscribe(bool writing, l4_cap_idx_t notifier)
5.58 {
5.59 - int i = writing ? 1 : 0;
5.60 - std::set<l4_cap_idx_t>::iterator it = _notifiers[i].find(notifier);
5.61 -
5.62 - if (it != _notifiers[i].end())
5.63 - {
5.64 - _notifiers[i].erase(it);
5.65 - _flags[i] = 0;
5.66 - _deferred[i] = 0;
5.67 - ipc_cap_free_um(notifier);
5.68 - }
5.69 + NotificationSupport::unsubscribe(writing ? 1 : 0, notifier);
5.70 }
5.71
5.72 /* Notify the other endpoint. */
5.73 @@ -93,27 +63,7 @@
5.74 {
5.75 /* Let the writer notify the reader, and the other way round. */
5.76
5.77 - int i = writing ? 0 : 1;
5.78 -
5.79 - /* Notify the other endpoint or hold any notification for potential future
5.80 - subscription. */
5.81 -
5.82 - if (!_notifiers[i].empty())
5.83 - {
5.84 - if (flags & _flags[i])
5.85 - {
5.86 - std::set<l4_cap_idx_t>::iterator it;
5.87 -
5.88 - for (it = _notifiers[i].begin(); it != _notifiers[i].end(); it++)
5.89 - {
5.90 - client_Notifier notifier(*it);
5.91 -
5.92 - notifier.notify(flags & _flags[i]);
5.93 - }
5.94 - }
5.95 - }
5.96 - else
5.97 - _deferred[i] = flags;
5.98 + NotificationSupport::notify(writing ? 0 : 1, flags);
5.99 }
5.100
5.101 /* Return whether one or more endpoints have detached. */
5.102 @@ -156,15 +106,7 @@
5.103
5.104 /* Release notifiers. */
5.105
5.106 - for (unsigned int i = 0; i < 2; i++)
5.107 - {
5.108 - std::set<l4_cap_idx_t>::iterator it;
5.109 -
5.110 - for (it = _notifiers[i].begin(); it != _notifiers[i].end(); it++)
5.111 - ipc_cap_free_um(*it);
5.112 -
5.113 - _notifiers[i].clear();
5.114 - }
5.115 + release_notifiers();
5.116
5.117 /* Delete the page collection and related objects. */
5.118