# HG changeset patch # User Paul Boddie # Date 1625867569 -7200 # Node ID 3bfe811802d29b967852aa0c5a1fca5baae19218 # Parent 7374a07a6bf8db21c79b3226c41d8c9b2476aca5 Support multiple notifiers for each pipe endpoint. diff -r 7374a07a6bf8 -r 3bfe811802d2 libfsclient/lib/src/notifier.cc --- a/libfsclient/lib/src/notifier.cc Fri Jul 09 00:15:29 2021 +0200 +++ b/libfsclient/lib/src/notifier.cc Fri Jul 09 23:52:49 2021 +0200 @@ -85,11 +85,15 @@ if (l4_is_invalid_cap(file->notifier)) return -L4_EINVAL; - ipc_cap_free_um(file->notifier); - client_Notification notify(file->ref); - return notify.unsubscribe(); + long err = notify.unsubscribe(file->notifier); + + if (err) + return err; + + ipc_cap_free_um(file->notifier); + return L4_EOK; } /* Handle a notification event for a file. Ideally, this would be invoked by the diff -r 7374a07a6bf8 -r 3bfe811802d2 libfsserver/include/fsserver/pipe_pager.h --- a/libfsserver/include/fsserver/pipe_pager.h Fri Jul 09 00:15:29 2021 +0200 +++ b/libfsserver/include/fsserver/pipe_pager.h Fri Jul 09 23:52:49 2021 +0200 @@ -78,7 +78,7 @@ virtual long subscribe(l4_cap_idx_t notifier, notify_flags_t flags); - virtual long unsubscribe(); + virtual long unsubscribe(l4_cap_idx_t notifier); }; // vim: tabstop=4 expandtab shiftwidth=4 diff -r 7374a07a6bf8 -r 3bfe811802d2 libfsserver/include/fsserver/pipe_paging.h --- a/libfsserver/include/fsserver/pipe_paging.h Fri Jul 09 00:15:29 2021 +0200 +++ b/libfsserver/include/fsserver/pipe_paging.h Fri Jul 09 23:52:49 2021 +0200 @@ -21,6 +21,8 @@ #pragma once +#include + #include #include #include @@ -56,7 +58,7 @@ /* Notification endpoints. */ - l4_cap_idx_t _notifiers[2]; + std::set _notifiers[2]; notify_flags_t _flags[2], _deferred[2]; /* Common functionality. */ @@ -77,7 +79,7 @@ virtual void subscribe(bool writing, l4_cap_idx_t notifier, notify_flags_t flags); - virtual void unsubscribe(bool writing); + virtual void unsubscribe(bool writing, l4_cap_idx_t notifier); /* Region management. */ diff -r 7374a07a6bf8 -r 3bfe811802d2 libfsserver/lib/pipes/pipe_pager.cc --- a/libfsserver/lib/pipes/pipe_pager.cc Fri Jul 09 00:15:29 2021 +0200 +++ b/libfsserver/lib/pipes/pipe_pager.cc Fri Jul 09 23:52:49 2021 +0200 @@ -174,9 +174,9 @@ return L4_EOK; } -long PipePager::unsubscribe() +long PipePager::unsubscribe(l4_cap_idx_t notifier) { - _paging->unsubscribe(_writing); + _paging->unsubscribe(_writing, notifier); return L4_EOK; } diff -r 7374a07a6bf8 -r 3bfe811802d2 libfsserver/lib/pipes/pipe_paging.cc --- a/libfsserver/lib/pipes/pipe_paging.cc Fri Jul 09 00:15:29 2021 +0200 +++ b/libfsserver/lib/pipes/pipe_paging.cc Fri Jul 09 23:52:49 2021 +0200 @@ -47,7 +47,6 @@ for (unsigned int i = 0; i < 2; i++) { - _notifiers[i] = L4_INVALID_CAP; _flags[i] = 0; _deferred[i] = 0; } @@ -59,10 +58,7 @@ { int i = writing ? 1 : 0; - if (l4_is_valid_cap(_notifiers[i])) - unsubscribe(writing); - - _notifiers[i] = notifier; + _notifiers[i].insert(notifier); _flags[i] = flags; /* Send deferred conditions on behalf of the other endpoint held before @@ -77,16 +73,17 @@ /* Unsubscribe from an endpoint's notifications. */ -void PipePaging::unsubscribe(bool writing) +void PipePaging::unsubscribe(bool writing, l4_cap_idx_t notifier) { int i = writing ? 1 : 0; + std::set::iterator it = _notifiers[i].find(notifier); - if (l4_is_valid_cap(_notifiers[i])) + if (it != _notifiers[i].end()) { - ipc_cap_free_um(_notifiers[i]); - _notifiers[i] = L4_INVALID_CAP; + _notifiers[i].erase(it); _flags[i] = 0; _deferred[i] = 0; + ipc_cap_free_um(notifier); } } @@ -101,13 +98,18 @@ /* Notify the other endpoint or hold any notification for potential future subscription. */ - if (l4_is_valid_cap(_notifiers[i])) + if (!_notifiers[i].empty()) { if (flags & _flags[i]) { - client_Notifier notifier(_notifiers[i]); + std::set::iterator it; - notifier.notify(flags & _flags[i]); + for (it = _notifiers[i].begin(); it != _notifiers[i].end(); it++) + { + client_Notifier notifier(*it); + + notifier.notify(flags & _flags[i]); + } } } else @@ -156,11 +158,12 @@ for (unsigned int i = 0; i < 2; i++) { - if (l4_is_valid_cap(_notifiers[i])) - { - ipc_cap_free_um(_notifiers[i]); - _notifiers[i] = L4_INVALID_CAP; - } + std::set::iterator it; + + for (it = _notifiers[i].begin(); it != _notifiers[i].end(); it++) + ipc_cap_free_um(*it); + + _notifiers[i].clear(); } /* Delete the page collection and related objects. */