# HG changeset patch # User Paul Boddie # Date 1677345013 -3600 # Node ID 9cdaf13d4f25dc762fbf06acd9e254747691a07b # Parent 9c5e1a1b92aaa157352ced6452c0494a642a90e9 Replaced special-case notifier handling with the more general notification support and client notifier mechanisms. diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libexec/include/exec/external_pager.h --- a/libexec/include/exec/external_pager.h Thu Feb 23 23:49:26 2023 +0100 +++ b/libexec/include/exec/external_pager.h Sat Feb 25 18:10:13 2023 +0100 @@ -22,6 +22,7 @@ #pragma once #include +#include #include "notifier_interface.h" #include "parent_pager_object_interface.h" @@ -30,10 +31,11 @@ /* A simple system pager also acting as a region mapper. */ -class ExternalPager : public ExecPager, public ParentPagerObject +class ExternalPager : public ExecPager, public ParentPagerObject, + public NotificationSupport { protected: - Notifier *_notifier = NULL; + unsigned int _endpoint; public: explicit ExternalPager(address_t start = 0, address_t end = 0); @@ -57,8 +59,11 @@ /* Notification methods. */ - virtual void set_notifier(Notifier *notifier) - { _notifier = notifier; } + virtual long subscribe(l4_cap_idx_t notifier, notify_flags_t flags) + { return NotificationSupport::subscribe(notifier, flags, this, &_endpoint); } + + virtual long unsubscribe() + { NotificationSupport::unsubscribe(_endpoint, this); return L4_EOK; } }; /* vim: tabstop=2 expandtab shiftwidth=2 diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libexec/include/exec/process_creating.h --- a/libexec/include/exec/process_creating.h Thu Feb 23 23:49:26 2023 +0100 +++ b/libexec/include/exec/process_creating.h Sat Feb 25 18:10:13 2023 +0100 @@ -84,7 +84,7 @@ virtual long start(file_t *file, int argc, const char *argv[]); - virtual void set_notifier(Notifier *notifier); + virtual l4_cap_idx_t get_pager(); }; /* vim: tabstop=2 expandtab shiftwidth=2 diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libexec/include/exec/process_creator_resource.h --- a/libexec/include/exec/process_creator_resource.h Thu Feb 23 23:49:26 2023 +0100 +++ b/libexec/include/exec/process_creator_resource.h Sat Feb 25 18:10:13 2023 +0100 @@ -47,7 +47,7 @@ /* Process creator interface methods. */ - virtual long start(l4_cap_idx_t program, l4_cap_idx_t notifier); + virtual long start(l4_cap_idx_t program, l4_cap_idx_t *process); }; /* vim: tabstop=2 expandtab shiftwidth=2 diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libexec/lib/src/external_pager.cc --- a/libexec/lib/src/external_pager.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libexec/lib/src/external_pager.cc Sat Feb 25 18:10:13 2023 +0100 @@ -39,7 +39,7 @@ /* A simple system pager also acting as a region mapper. */ ExternalPager::ExternalPager(address_t start, address_t end) -: ExecPager(start, end) +: ExecPager(start, end), NotificationSupport() { } @@ -163,8 +163,7 @@ long ExternalPager::signal(unsigned long sig, unsigned long val) { - if (_notifier != NULL) - _notifier->notify(NOTIFY_TASK_SIGNAL, (notify_values_t) {sig, val}); + notify_all(NOTIFY_TASK_SIGNAL, (notify_values_t) {sig, val}); return L4_EOK; } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libexec/lib/src/process_creating.cc --- a/libexec/lib/src/process_creating.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libexec/lib/src/process_creating.cc Sat Feb 25 18:10:13 2023 +0100 @@ -313,11 +313,11 @@ return start_program(argc, argv); } -/* Set the given notifier on the system-level pager for a process. */ +/* Get a reference to the system-level pager for a process. */ -void ProcessCreating::set_notifier(Notifier *notifier) +l4_cap_idx_t ProcessCreating::get_pager() { - _exec_pager.set_notifier(notifier); + return _config.server; } /* vim: tabstop=2 expandtab shiftwidth=2 diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libexec/lib/src/process_creator_resource.cc --- a/libexec/lib/src/process_creator_resource.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libexec/lib/src/process_creator_resource.cc Sat Feb 25 18:10:13 2023 +0100 @@ -49,7 +49,7 @@ /* ProcessCreator interface methods. */ -long ProcessCreatorResource::start(l4_cap_idx_t program, l4_cap_idx_t notifier) +long ProcessCreatorResource::start(l4_cap_idx_t program, l4_cap_idx_t *process) { file_t file; @@ -70,11 +70,9 @@ if (err) return err; - /* NOTE: To be managed properly. */ + /* Obtain a reference to the pager to interact with the process. */ - client_Notifier *n = new client_Notifier(notifier); - - set_notifier(n); + *process = get_pager(); return L4_EOK; } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsclient/include/fsclient/process.h --- a/libfsclient/include/fsclient/process.h Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsclient/include/fsclient/process.h Sat Feb 25 18:10:13 2023 +0100 @@ -58,7 +58,7 @@ process_t *process_new(); void process_init(process_t *process); -long process_start(process_t *process, file_t *file, process_notifier_t *notifier); +long process_start(process_t *process, file_t *file); /* Notification support. */ @@ -68,8 +68,8 @@ void process_notify_close(process_notifier_t *notifier); process_notifier_t *process_notify_local(); process_notifier_t *process_notify_task(); -long process_notify_get_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t *endpoint); -long process_notify_remove_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t endpoint); +long process_notify_subscribe(process_t *process, notify_flags_t flags, process_notifier_t *notifier); +long process_notify_unsubscribe(process_t *process, process_notifier_t *notifier); long process_notify_wait_process(process_t *process, process_notifier_t *notifier); long process_notify_wait_processes(process_t **process, process_notifier_t *notifier); diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsclient/lib/src/process.cc --- a/libfsclient/lib/src/process.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsclient/lib/src/process.cc Sat Feb 25 18:10:13 2023 +0100 @@ -62,28 +62,20 @@ NOTE: This does not yet communicate arguments or obtain input/output pipes. */ -long process_start(process_t *process, file_t *file, process_notifier_t *notifier) +long process_start(process_t *process, file_t *file) { l4_cap_idx_t server = l4re_env_get_cap("pserver"); if (l4_is_invalid_cap(server)) return -L4_ENOMEM; - /* Obtain a notification endpoint. */ - - l4_cap_idx_t endpoint; - long err = process_notify_get_endpoint(process, notifier, &endpoint); - - if (err) - return err; - /* Obtain a client for the process creator. */ client_ProcessCreator creator(server); - /* Start the process, supplying the given endpoint. */ + /* Start the process, obtaining a reference to it. */ - return creator.start(file->ref, endpoint); + return creator.start(file->ref, &process->ref); } @@ -149,16 +141,16 @@ /* Subscribe to notification events on a process. */ -long process_notify_get_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t *endpoint) +long process_notify_subscribe(process_t *process, notify_flags_t flags, process_notifier_t *notifier) { - return notifier->obj->get_endpoint(process_notifiable(process), endpoint, true); + return notifier->obj->subscribe(process_notifiable(process), flags); } /* Unsubscribe from notification events on a process. */ -long process_notify_remove_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t endpoint) +long process_notify_unsubscribe(process_t *process, process_notifier_t *notifier) { - return notifier->obj->remove_endpoint(process_notifiable(process), endpoint); + return notifier->obj->unsubscribe(process_notifiable(process)); } /* Wait for a notification event on a process. */ @@ -168,10 +160,11 @@ SpecificObjectNotifier *specific_notifier = dynamic_cast(notifier->obj); long err = specific_notifier->wait_object(process_notifiable(process)); - /* Unsubscribe if a closure notification has been received. */ + /* Unsubscribe if a termination notification has been received. */ - //if (!err && (process->notifiable.notifications & NOTIFY_PEER_CLOSED)) - //process_notify_unsubscribe(process, notifier); + if (!err && (process->notifiable.notifications & NOTIFY_TASK_SIGNAL) && + (process->notifiable.values.sig == 0)) + process_notify_unsubscribe(process, notifier); return err; } @@ -186,10 +179,11 @@ *process = (process_t *) notifiable->base; - /* Unsubscribe if a closure notification has been received. */ + /* Unsubscribe if a termination notification has been received. */ - //if (!err && ((*file)->notifiable.notifications & NOTIFY_PEER_CLOSED)) - //file_notify_unsubscribe(*file, notifier); + if (!err && ((*process)->notifiable.notifications & NOTIFY_TASK_SIGNAL) && + ((*process)->notifiable.values.sig == 0)) + process_notify_unsubscribe(*process, notifier); return err; } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsserver/include/fsserver/notification.h --- a/libfsserver/include/fsserver/notification.h Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsserver/include/fsserver/notification.h Sat Feb 25 18:10:13 2023 +0100 @@ -1,7 +1,7 @@ /* * Notification support. * - * Copyright (C) 2021, 2022 Paul Boddie + * Copyright (C) 2021, 2022, 2023 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -45,7 +45,14 @@ { public: NotifierSet notifiers; - notify_flags_t flags = 0, deferred = 0; + + /* Notification flag mask, deferred flags. */ + + notify_flags_t flags = 0, deferred_flags = 0; + + /* Deferred values. */ + + notify_values_t deferred_values = NOTIFY_VALUES_NULL; }; typedef std::vector NotificationEndpointList; @@ -74,11 +81,13 @@ /* Deferred notifications for new endpoints. */ - notify_flags_t _deferred = 0; + notify_flags_t _deferred_flags = 0; + notify_values_t _deferred_values = NOTIFY_VALUES_NULL; virtual void release_notifiers(); - virtual void _notify(unsigned int endpoint, notify_flags_t flags); + virtual void _notify(unsigned int endpoint, notify_flags_t flags, + notify_values_t values); virtual long _subscribe(unsigned int endpoint, l4_cap_idx_t notifier, notify_flags_t flags, void *subscriber); @@ -90,11 +99,13 @@ virtual ~NotificationSupport(); - virtual void notify(unsigned int endpoint, notify_flags_t flags); + virtual void notify(unsigned int endpoint, notify_flags_t flags, + notify_values_t values); - virtual void notify_all(notify_flags_t flags); + virtual void notify_all(notify_flags_t flags, notify_values_t values); - virtual void notify_others(unsigned int endpoint, notify_flags_t flags); + virtual void notify_others(unsigned int endpoint, notify_flags_t flags, + notify_values_t values); virtual long subscribe(l4_cap_idx_t notifier, notify_flags_t flags, void *subscriber, unsigned int *endpoint_number); diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsserver/lib/files/file_pager.cc --- a/libfsserver/lib/files/file_pager.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsserver/lib/files/file_pager.cc Sat Feb 25 18:10:13 2023 +0100 @@ -52,7 +52,7 @@ { /* Notify other users of the file and unsubscribe. */ - _provider->notify_others(_endpoint, NOTIFY_PEER_CLOSED); + _provider->notify_others(_endpoint, NOTIFY_PEER_CLOSED, NOTIFY_VALUES_NULL); unsubscribe(); /* Detach the pager, potentially removing the file provider. */ @@ -70,7 +70,7 @@ if (_resized) { - _provider->notify_others(_endpoint, NOTIFY_CONTENT_AVAILABLE); + _provider->notify_others(_endpoint, NOTIFY_CONTENT_AVAILABLE, NOTIFY_VALUES_NULL); _resized = false; } @@ -86,7 +86,7 @@ if (err) return err; - _provider->notify_all(NOTIFY_FILE_OPENED); + _provider->notify_all(NOTIFY_FILE_OPENED, NOTIFY_VALUES_NULL); return ResourceServer(resource).start_thread(file); } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsserver/lib/files/opener_resource.cc --- a/libfsserver/lib/files/opener_resource.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsserver/lib/files/opener_resource.cc Sat Feb 25 18:10:13 2023 +0100 @@ -1,7 +1,7 @@ /* * A resource offering support for creating contexts and opening files. * - * Copyright (C) 2021, 2022 Paul Boddie + * Copyright (C) 2021, 2022, 2023 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -67,7 +67,7 @@ NOTE: This should also communicate which file was involved, probably NOTE: using the file identifier of the opened file. */ - provider->notify_all(NOTIFY_FILE_OPENED); + provider->notify_all(NOTIFY_FILE_OPENED, NOTIFY_VALUES_NULL); return L4_EOK; } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsserver/lib/generic/notification.cc --- a/libfsserver/lib/generic/notification.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsserver/lib/generic/notification.cc Sat Feb 25 18:10:13 2023 +0100 @@ -51,10 +51,13 @@ unsigned int endpoint = _endpoints.size(); _endpoints.resize(endpoint + 1); - /* Propagate deferred flags for new endpoints. */ + /* Propagate deferred flags and values for new endpoints. */ - if (_deferred) - _endpoints[endpoint].deferred = _deferred; + if (_deferred_flags) + { + _endpoints[endpoint].deferred_flags = _deferred_flags; + _endpoints[endpoint].deferred_values = _deferred_values; + } *endpoint_number = endpoint; return _subscribe(endpoint, notifier, flags, subscriber); @@ -73,8 +76,11 @@ /* Propagate deferred flags for new endpoints. */ - if (_deferred) - _endpoints[endpoint].deferred = _deferred; + if (_deferred_flags) + { + _endpoints[endpoint].deferred_flags = _deferred_flags; + _endpoints[endpoint].deferred_values = _deferred_values; + } return _subscribe(endpoint, notifier, flags, subscriber); } @@ -102,10 +108,11 @@ /* Send deferred conditions held from before subscription occurred. */ - if (ep.deferred) + if (ep.deferred_flags) { - _notify(endpoint, ep.deferred); - ep.deferred = 0; + _notify(endpoint, ep.deferred_flags, ep.deferred_values); + ep.deferred_flags = 0; + ep.deferred_values = NOTIFY_VALUES_NULL; } /* Record the subscriber's notifier. */ @@ -143,21 +150,24 @@ if (ep.notifiers.empty()) { ep.flags = 0; - ep.deferred = 0; + ep.deferred_flags = 0; + ep.deferred_values = NOTIFY_VALUES_NULL; } } } /* Notify a particular endpoint. */ -void NotificationSupport::notify(unsigned int endpoint, notify_flags_t flags) +void NotificationSupport::notify(unsigned int endpoint, notify_flags_t flags, + notify_values_t values) { std::lock_guard guard(_lock); - _notify(endpoint, flags); + _notify(endpoint, flags, values); } -void NotificationSupport::_notify(unsigned int endpoint, notify_flags_t flags) +void NotificationSupport::_notify(unsigned int endpoint, notify_flags_t flags, + notify_values_t values) { if (endpoint >= _endpoints.size()) return; @@ -177,37 +187,47 @@ { client_Notifier notifier(*it); - notifier.notify(flags & ep.flags, (notify_values_t) NOTIFY_VALUES_NULL); + notifier.notify(flags & ep.flags, values); } } } else - ep.deferred = flags; + { + ep.deferred_flags = flags; + ep.deferred_values = values; + } } /* Notify all endpoints. */ -void NotificationSupport::notify_all(notify_flags_t flags) +void NotificationSupport::notify_all(notify_flags_t flags, notify_values_t values) { std::lock_guard guard(_lock); for (unsigned int i = 0; i < _endpoints.size(); i++) - _notify(i, flags); + _notify(i, flags, values); - _deferred |= flags; + /* Accumulate flags, but only record the most recent values. */ + + _deferred_flags |= flags; + _deferred_values = values; } /* Notify the other endpoints. */ -void NotificationSupport::notify_others(unsigned int endpoint, notify_flags_t flags) +void NotificationSupport::notify_others(unsigned int endpoint, notify_flags_t flags, + notify_values_t values) { std::lock_guard guard(_lock); for (unsigned int i = 0; i < _endpoints.size(); i++) if (i != endpoint) - _notify(i, flags); + _notify(i, flags, values); - _deferred |= flags; + /* Accumulate flags, but only record the most recent values. */ + + _deferred_flags |= flags; + _deferred_values = values; } /* Release notifiers for each endpoint. */ @@ -226,7 +246,8 @@ ep.notifiers.clear(); ep.flags = 0; - ep.deferred = 0; + ep.deferred_flags = 0; + ep.deferred_values = NOTIFY_VALUES_NULL; } } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsserver/lib/pipes/pipe_pager.cc --- a/libfsserver/lib/pipes/pipe_pager.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsserver/lib/pipes/pipe_pager.cc Sat Feb 25 18:10:13 2023 +0100 @@ -62,7 +62,8 @@ /* Notify the other endpoint and unsubscribe. */ - _paging->notify_others(_writing ? PipePaging::WRITER : PipePaging::READER, NOTIFY_PEER_CLOSED); + _paging->notify_others(_writing ? PipePaging::WRITER : PipePaging::READER, + NOTIFY_PEER_CLOSED, NOTIFY_VALUES_NULL); unsubscribe(); /* Deallocate the paging coordinator if no other endpoints are active. */ @@ -170,7 +171,8 @@ // NOTE: Perhaps employ a distinct event type for metadata updates. _paging->notify_others(_writing ? PipePaging::WRITER : PipePaging::READER, - NOTIFY_CONTENT_AVAILABLE | NOTIFY_SPACE_AVAILABLE); + NOTIFY_CONTENT_AVAILABLE | NOTIFY_SPACE_AVAILABLE, + NOTIFY_VALUES_NULL); return L4_EOK; } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libfsserver/lib/pipes/pipe_paging.cc --- a/libfsserver/lib/pipes/pipe_paging.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/libfsserver/lib/pipes/pipe_paging.cc Sat Feb 25 18:10:13 2023 +0100 @@ -135,7 +135,7 @@ /* Let the writer notify the reader. */ - notify_others(PipePaging::WRITER, NOTIFY_CONTENT_AVAILABLE); + notify_others(PipePaging::WRITER, NOTIFY_CONTENT_AVAILABLE, NOTIFY_VALUES_NULL); /* Return the next region's mapper. */ @@ -186,7 +186,7 @@ /* Let the reader notify the writer. */ - notify_others(PipePaging::READER, NOTIFY_SPACE_AVAILABLE); + notify_others(PipePaging::READER, NOTIFY_SPACE_AVAILABLE, NOTIFY_VALUES_NULL); return mapper; } diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libsystypes/idl/parent_pager_object.idl --- a/libsystypes/idl/parent_pager_object.idl Thu Feb 23 23:49:26 2023 +0100 +++ b/libsystypes/idl/parent_pager_object.idl Sat Feb 25 18:10:13 2023 +0100 @@ -1,4 +1,5 @@ +import "notification.idl"; import "pager_object.idl"; import "parent.idl"; -interface ParentPagerObject composes Parent, PagerObject; +interface ParentPagerObject composes Parent, PagerObject, Notification; diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 libsystypes/idl/process_creator.idl --- a/libsystypes/idl/process_creator.idl Thu Feb 23 23:49:26 2023 +0100 +++ b/libsystypes/idl/process_creator.idl Sat Feb 25 18:10:13 2023 +0100 @@ -1,7 +1,6 @@ interface ProcessCreator { - /* Start a process, using the given file reference as the payload, indicating - a notifier to receive notifications. */ + /* Start a process, using the given file reference as the payload. */ - [opcode(30)] void start(in cap program, in cap notifier); + [opcode(30)] void start(in cap program, out cap process); }; diff -r 9c5e1a1b92aa -r 9cdaf13d4f25 tests/dstest_exec.cc --- a/tests/dstest_exec.cc Thu Feb 23 23:49:26 2023 +0100 +++ b/tests/dstest_exec.cc Sat Feb 25 18:10:13 2023 +0100 @@ -52,15 +52,13 @@ return 1; } - /* Create a new process structure and obtain the common notifier. */ + /* Create a new process structure. */ process_t *process = process_new(); - process_notifier_t *notifier = process_notify_task(); - /* Start a process for the given program, specifying a notifier from which an - endpoint will be obtained for notifications. */ + /* Start a process for the given program. */ - err = process_start(process, program_file, notifier); + err = process_start(process, program_file); /* NOTE: Need to be able to send arguments, which would be sent via a context, although capabilities could be sent via arguments. */ @@ -73,10 +71,30 @@ printf("Finished program initiation.\n"); + /* Obtain the common notifier. */ + + process_notifier_t *notifier = process_notify_task(); + + /* Subscribe to the process for notifications. */ + + err = process_notify_subscribe(process, NOTIFY_TASK_SIGNAL, notifier); + + if (err) + { + printf("Could not subscribe to process: %s\n", l4sys_errtostr(err)); + return 1; + } + /* Wait for a signal from the process. */ err = process_notify_wait_process(process, notifier); + if (err) + { + printf("Could not wait for process: %s\n", l4sys_errtostr(err)); + return 1; + } + notify_flags_t flags = process_notifications(process); notify_values_t values = process_notification_values(process);