# HG changeset patch # User Paul Boddie # Date 1679615186 -3600 # Node ID f2f170ce32e85b36c7feccb5f24f51f59c9f90f8 # Parent c28f4b1c2dc2315fb356739ef85d0d80f763e700 Changed the process monitoring architecture, separating monitoring of the actual program from that done by the external pager of the internal pager/region mapper. diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/include/exec/external_pager.h --- a/libexec/include/exec/external_pager.h Thu Mar 23 15:42:39 2023 +0100 +++ b/libexec/include/exec/external_pager.h Fri Mar 24 00:46:26 2023 +0100 @@ -21,12 +21,10 @@ #pragma once -#include - #include #include +#include #include -#include #include #include "parent_pager_object_interface.h" @@ -36,17 +34,18 @@ /* A simple system pager also acting as a region mapper. */ class ExternalPager : public ExecPager, public ParentPagerObject, - public NotificationSupport, public Resource + public Resource { protected: /* Resources associated with the created process. */ l4_cap_idx_t _task = L4_INVALID_CAP, _mapped_task = L4_INVALID_CAP, + _thread = L4_INVALID_CAP, _mapped_thread = L4_INVALID_CAP, _parent = L4_INVALID_CAP, _mapped_parent = L4_INVALID_CAP, - _pager = L4_INVALID_CAP, _mapped_pager = L4_INVALID_CAP, - _ipc_gate = L4_INVALID_CAP; - std::vector _threads, _mapped_threads; + _pager = L4_INVALID_CAP, _mapped_pager = L4_INVALID_CAP; + + ProcessMonitor *_monitor = NULL; /* Resources supporting the internal pager. */ @@ -63,13 +62,16 @@ virtual void *interface() { return static_cast(this); } - /* Task and thread management. */ + /* Capability management. */ - virtual void add_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); - virtual void set_gate(l4_cap_idx_t cap); virtual void set_pager(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); virtual void set_parent(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); virtual void set_task(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); + virtual void set_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); + + /* Lifecycle management. */ + + virtual void set_monitor(ProcessMonitor *monitor); /* Internal pager resource management. */ @@ -96,12 +98,6 @@ /* Parent methods. */ virtual long signal(unsigned long sig, unsigned long val); - - /* Notification methods. */ - - virtual long subscribe(l4_cap_idx_t notifier, notify_flags_t flags); - - virtual long unsubscribe(l4_cap_idx_t notifier); }; /* vim: tabstop=2 expandtab shiftwidth=2 diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/include/exec/process.h --- a/libexec/include/exec/process.h Thu Mar 23 15:42:39 2023 +0100 +++ b/libexec/include/exec/process.h Fri Mar 24 00:46:26 2023 +0100 @@ -96,9 +96,9 @@ long configure_task(l4_cap_idx_t *task, l4_cap_idx_t *mapped_task, unsigned int threads = 2); - long configure_thread(l4_cap_idx_t rm, l4_cap_idx_t *mapped_rm = NULL); + long set_pager(l4_cap_idx_t rm, l4_cap_idx_t *mapped_rm = NULL); - long set_parent(l4_cap_idx_t parent, l4_cap_idx_t *mapped_parent); + long set_parent(l4_cap_idx_t parent, l4_cap_idx_t *mapped_parent = NULL); long map_capabilities(struct ipc_mapped_cap mapped_caps[], bool to_count = true); diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/include/exec/process_creating.h --- a/libexec/include/exec/process_creating.h Thu Mar 23 15:42:39 2023 +0100 +++ b/libexec/include/exec/process_creating.h Fri Mar 24 00:46:26 2023 +0100 @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -43,9 +44,10 @@ const char *_rm_filename; file_t *_rm_file; - /* External pager configuration. */ + /* External pager and process monitor. */ ExternalPager *_exec_pager = NULL; + ProcessMonitor *_monitor = NULL; /* Process construction. */ @@ -62,7 +64,7 @@ /* IPC gate for communication within the created task, plus allocated capability. */ - l4_cap_idx_t _ipc_gate, _ipc_gate_cap; + l4_cap_idx_t _internal_pager, _mapped_internal_pager; /* Utility methods. */ @@ -74,9 +76,11 @@ long init_external_pager(l4_cap_idx_t *pager); - long configure_task(l4_cap_idx_t pager); + long init_process_monitor(l4_cap_idx_t *monitor); - long create_ipc_gate(); + long configure_task(); + + long allocate_internal_pager(); void init_region(struct exec_region *regions, struct ipc_mapped_cap *mapped_caps, @@ -84,7 +88,7 @@ long start_region_mapper(l4_cap_idx_t pager); - long start_program(int argc, const char *argv[]); + long start_program(l4_cap_idx_t monitor, int argc, const char *argv[]); public: explicit ProcessCreating(const char *rm_filename, file_t *rm_file); diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/include/exec/process_monitor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libexec/include/exec/process_monitor.h Fri Mar 24 00:46:26 2023 +0100 @@ -0,0 +1,82 @@ +/* + * A process monitor abstraction. + * + * Copyright (C) 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#pragma once + +#include +#include + +#include "parent_notification_object_interface.h" + + + +/* A process monitor receiving signals from a task. */ + +class ProcessMonitor : public ParentNotificationObject, public NotificationSupport, + public Resource +{ +protected: + + /* Resources associated with the created process. */ + + l4_cap_idx_t _pager = L4_INVALID_CAP, _mapped_pager = L4_INVALID_CAP, + _parent = L4_INVALID_CAP, _mapped_parent = L4_INVALID_CAP, + _task = L4_INVALID_CAP, _mapped_task = L4_INVALID_CAP, + _thread = L4_INVALID_CAP, _mapped_thread = L4_INVALID_CAP; + +public: + explicit ProcessMonitor(); + + /* Server details. */ + + virtual ipc_server_default_config_type config(); + + virtual void *interface() + { return static_cast(this); } + + /* Capability management. */ + + virtual void set_pager(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); + virtual void set_parent(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); + virtual void set_task(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); + virtual void set_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap); + + /* Lifecycle management. */ + + virtual void pager_ended(); + + /* Resource methods. */ + + virtual void close(); + + /* Parent methods. */ + + virtual long signal(unsigned long sig, unsigned long val); + + /* Notification methods. */ + + virtual long subscribe(l4_cap_idx_t notifier, notify_flags_t flags); + + virtual long unsubscribe(l4_cap_idx_t notifier); +}; + +/* vim: tabstop=2 expandtab shiftwidth=2 +*/ diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/lib/src/Makefile --- a/libexec/lib/src/Makefile Thu Mar 23 15:42:39 2023 +0100 +++ b/libexec/lib/src/Makefile Fri Mar 24 00:46:26 2023 +0100 @@ -17,7 +17,9 @@ CLIENT_INTERFACES_CC = dataspace -SERVER_INTERFACES_CC = opener pager_object parent_pager_object process_creator_context_object +SERVER_INTERFACES_CC = \ + opener pager_object parent_notification_object \ + parent_pager_object process_creator_context_object # Generated and plain source files. @@ -36,6 +38,7 @@ process.cc process_creating.cc \ process_creator_context_resource.cc \ process_creator_resource.cc \ + process_monitor.cc \ segment.cc stack.cc # Normal definitions. diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/lib/src/external_pager.cc --- a/libexec/lib/src/external_pager.cc Thu Mar 23 15:42:39 2023 +0100 +++ b/libexec/lib/src/external_pager.cc Fri Mar 24 00:46:26 2023 +0100 @@ -43,7 +43,7 @@ /* A simple system pager also acting as a region mapper. */ ExternalPager::ExternalPager(address_t start, address_t end) -: ExecPager(start, end), NotificationSupport() +: ExecPager(start, end) { } @@ -94,30 +94,15 @@ for (itc = _dataspaces.begin(); itc != _dataspaces.end(); itc++) ipc_cap_free_um(*itc); - /* Remove the created task. */ + /* Notify the monitor. */ - if (l4_is_valid_cap(_task)) - { - ipc_unmap_capability(_task, _mapped_task); - ipc_cap_free_um(_task); - _task = L4_INVALID_CAP; - } + if (_monitor != NULL) + _monitor->pager_ended(); } -/* Manage the task and thread capabilities. */ - -void ExternalPager::add_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) -{ - _threads.push_back(cap); - _mapped_threads.push_back(mapped_cap); -} - -void ExternalPager::set_gate(l4_cap_idx_t cap) -{ - _ipc_gate = cap; -} +/* Capability management. */ void ExternalPager::set_pager(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) { @@ -137,6 +122,21 @@ _mapped_task = mapped_cap; } +void ExternalPager::set_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) +{ + _thread = cap; + _mapped_thread = mapped_cap; +} + + + +/* Lifecycle management. */ + +void ExternalPager::set_monitor(ProcessMonitor *monitor) +{ + _monitor = monitor; +} + /* Manage pager resources. */ @@ -277,41 +277,23 @@ long ExternalPager::signal(unsigned long sig, unsigned long val) { - notify_all(NOTIFY_TASK_SIGNAL, (notify_values_t) {sig, val}); - - /* Handle the termination event. */ + /* Handle the termination event of the internal pager. */ if (sig == 0) { - printf("Signal from task.\n"); - - /* Once the program exits, the IPC gate connecting the program with its - internal pager can be released. */ + printf("Signal from internal pager.\n"); - if (l4_is_valid_cap(_ipc_gate)) - { - ipc_cap_free_um(_ipc_gate); - _ipc_gate = L4_INVALID_CAP; - } - - /* Upon exit of the program's internal pager, release the capabilities - associated with this server. */ + /* For some reason, threads cannot be released by the process, so they are + also unmapped on its behalf. */ - else if (l4_is_valid_cap(_task)) + if (l4_is_valid_cap(_thread)) { - /* Threads. For some reason, these cannot be released by the process, so - they are also unmapped on its behalf. */ - - std::vector::iterator it; + ipc_cap_free_um(_thread); + ipc_unmap_capability(_task, _mapped_thread); + _thread = L4_INVALID_CAP; - for (it = _threads.begin(); it != _threads.end(); it++) - ipc_cap_free_um(*it); - - for (it = _mapped_threads.begin(); it != _mapped_threads.end(); it++) - ipc_unmap_capability(_task, *it); - - /* Parent and pager/region mapper. Freeing these after the threads should - avoid warnings about invalid pager capabilities. */ + /* Parent and pager/region mapper. Freeing the pager after the thread + should avoid warnings about invalid pager capabilities. */ ipc_unmap_capability(_task, _mapped_parent); ipc_unmap_capability(_task, _mapped_pager); @@ -321,21 +303,5 @@ return L4_EOK; } - - -/* Subscribe to notifications. */ - -long ExternalPager::subscribe(l4_cap_idx_t notifier, notify_flags_t flags) -{ - return NotificationSupport::subscribe(notifier, flags); -} - -/* Unsubscribe from notifications. */ - -long ExternalPager::unsubscribe(l4_cap_idx_t notifier) -{ - return NotificationSupport::unsubscribe(notifier); -} - /* vim: tabstop=2 expandtab shiftwidth=2 */ diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/lib/src/process.cc --- a/libexec/lib/src/process.cc Thu Mar 23 15:42:39 2023 +0100 +++ b/libexec/lib/src/process.cc Fri Mar 24 00:46:26 2023 +0100 @@ -67,7 +67,6 @@ _env.log = L4_BASE_LOG_CAP; _env.scheduler = L4_BASE_SCHEDULER_CAP; _env.mem_alloc = L4_EXEC_MA_CAP; - _env.parent = L4_EXEC_PARENT_CAP; /* Capability details that are updated for each thread. Note that the region mapper is redefined, but it would traditionally employ the given index. */ @@ -156,10 +155,10 @@ return map_capabilities(mapped_caps, false); } -/* Configure the thread environment, employing the given capability for the - region mapper, returning its capability details in the new task. */ +/* Set the pager/region mapper of the new thread, using the given capability, + returning its capability details in the new task. */ -long Process::configure_thread(l4_cap_idx_t rm, l4_cap_idx_t *mapped_rm) +long Process::set_pager(l4_cap_idx_t rm, l4_cap_idx_t *mapped_rm) { /* Employ a distinct region mapper for each thread's environment, this acting as pager. */ @@ -173,16 +172,28 @@ { _env.rm = allocate_cap(); *mapped_rm = _env.rm; - return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.rm, rm, L4_CAP_FPAGE_RWS, 0}); + return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.rm, rm, + L4_CAP_FPAGE_RWS, L4_FPAGE_C_OBJ_RIGHTS}); } } -/* Set the parent of the new thread. */ +/* Set the parent of the new thread, using the default parent capability index + if no mapped capability is provided. */ long Process::set_parent(l4_cap_idx_t parent, l4_cap_idx_t *mapped_parent) { - *mapped_parent = _env.parent; - return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.parent, parent, L4_CAP_FPAGE_RWS, 0}); + if ((mapped_parent != NULL) && l4_is_valid_cap(*mapped_parent)) + { + _env.parent = *mapped_parent; + return L4_EOK; + } + else + { + _env.parent = L4_EXEC_PARENT_CAP; + *mapped_parent = _env.parent; + return ipc_map_capability(_task, (struct ipc_mapped_cap) {_env.parent, + parent, L4_CAP_FPAGE_RWS, 0}); + } } /* Map capabilities into the task, counting them if indicated. If capability diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/lib/src/process_creating.cc --- a/libexec/lib/src/process_creating.cc Thu Mar 23 15:42:39 2023 +0100 +++ b/libexec/lib/src/process_creating.cc Fri Mar 24 00:46:26 2023 +0100 @@ -111,9 +111,26 @@ return L4_EOK; } +/* Initialise a resource to receive signals from the process. */ + +long ProcessCreating::init_process_monitor(l4_cap_idx_t *monitor) +{ + _monitor = new ProcessMonitor; + + /* Start the monitor in a separate thread. */ + + long err = ResourceServer(_monitor).start_thread(monitor); + + if (err) + return err; + + _exec_pager->set_monitor(_monitor); + return L4_EOK; +} + /* Configure the environment for the task. */ -long ProcessCreating::configure_task(l4_cap_idx_t pager) +long ProcessCreating::configure_task() { l4_cap_idx_t task, mapped_task; long err = _process.configure_task(&task, &mapped_task); @@ -121,51 +138,32 @@ if (err) return err; - /* Record the task details in the pager for eventual resource deallocation. */ + /* Record the task details elsewhere for eventual resource deallocation. */ _exec_pager->set_task(task, mapped_task); - - /* Note the pager as the parent of the new task, recording its capability - details in the new task. */ - - l4_cap_idx_t mapped_parent; - err = _process.set_parent(pager, &mapped_parent); - - if (err) - return err; - - _exec_pager->set_parent(pager, mapped_parent); + _monitor->set_task(task, mapped_task); return L4_EOK; } -/* Create an unbound IPC gate for the region mapper and allocate it in the - created process. */ +/* Create an unbound IPC gate for the internal pager/region mapper and allocate + it in the created process. */ -long ProcessCreating::create_ipc_gate() +long ProcessCreating::allocate_internal_pager() { - _ipc_gate_cap = _process.allocate_cap(); - _ipc_gate = ipc_cap_alloc(); + _mapped_internal_pager = _process.allocate_cap(); + _internal_pager = ipc_cap_alloc(); - if (l4_is_invalid_cap(_ipc_gate)) + if (l4_is_invalid_cap(_internal_pager)) return -L4_ENOMEM; - long err = l4_error(l4_factory_create_gate(l4re_env()->factory, _ipc_gate, L4_INVALID_CAP, 0)); - - if (err) - return err; - - /* The gate is retained because even after being mapped to the new task, - releasing it will cause it to be deallocated. */ - - _exec_pager->set_gate(_ipc_gate); - return L4_EOK; + return l4_error(l4_factory_create_gate(l4re_env()->factory, _internal_pager, L4_INVALID_CAP, 0)); } /* Initialise and assign a region in a list to the created process. */ void ProcessCreating::init_region(struct exec_region *regions, - struct ipc_mapped_cap *mapped_caps, - struct exec_region &r, unsigned int &index) + struct ipc_mapped_cap *mapped_caps, + struct exec_region &r, unsigned int &index) { l4_cap_idx_t mapped_cap = _process.allocate_cap(); @@ -217,9 +215,11 @@ rm_regions[rm_index] = (struct exec_region) {0, 0, 0, L4_INVALID_CAP}; - /* Introduce the server capability and terminate the capability array. */ + /* Introduce the internal pager capability and terminate the capability array. */ - rm_mapped_caps[rm_index++] = (struct ipc_mapped_cap) {_ipc_gate_cap, _ipc_gate, L4_CAP_FPAGE_RWS, L4_FPAGE_C_OBJ_RIGHTS}; + rm_mapped_caps[rm_index++] = (struct ipc_mapped_cap) {_mapped_internal_pager, + _internal_pager, L4_CAP_FPAGE_RWS, + L4_FPAGE_C_OBJ_RIGHTS}; rm_mapped_caps[rm_index] = (struct ipc_mapped_cap) {0, L4_INVALID_CAP, 0, 0}; /* Map these additional capabilities. */ @@ -234,7 +234,7 @@ mapping the capability and encoded in the entry below. */ l4re_env_cap_entry_t rm_init_caps[] = { - l4re_env_cap_entry_t(ENV_INTERNAL_PAGER_NAME, _ipc_gate_cap, L4_CAP_FPAGE_RWS), + l4re_env_cap_entry_t(ENV_INTERNAL_PAGER_NAME, _mapped_internal_pager, L4_CAP_FPAGE_RWS), l4re_env_cap_entry_t() }; @@ -246,13 +246,23 @@ exception handler plus region mapper). */ l4_cap_idx_t mapped_pager = L4_INVALID_CAP; - err = _process.configure_thread(pager, &mapped_pager); + err = _process.set_pager(pager, &mapped_pager); if (err) return err; _exec_pager->set_pager(pager, mapped_pager); + /* Note the pager as the parent of the new task, recording its capability + details in the new task. */ + + err = _process.set_parent(pager, &mapped_pager); + + if (err) + return err; + + _exec_pager->set_parent(pager, mapped_pager); + /* Populate a thread stack with argument and environment details for the region mapper, plus the initial server capability and region details. */ @@ -271,14 +281,14 @@ if (err) return err; - _exec_pager->add_thread(thread, mapped_thread); + _exec_pager->set_thread(thread, mapped_thread); return L4_EOK; } /* Configure a thread for a program, populate its stack, and start the thread. */ -long ProcessCreating::start_program(int argc, const char *argv[]) +long ProcessCreating::start_program(l4_cap_idx_t monitor, int argc, const char *argv[]) { /* NOTE: Environment vector is currently not defined. */ @@ -287,12 +297,25 @@ /* Configure the environment for the thread, specifying the pager (and exception handler plus region mapper). */ - l4_cap_idx_t mapped_pager = _ipc_gate_cap; - long err = _process.configure_thread(_ipc_gate, &mapped_pager); + l4_cap_idx_t mapped_pager = _mapped_internal_pager; + long err = _process.set_pager(_internal_pager, &mapped_pager); if (err) return err; + _monitor->set_pager(_internal_pager, _mapped_internal_pager); + + /* Note the monitor as the parent of the new task, recording its capability + details in the new task. */ + + l4_cap_idx_t mapped_parent = L4_INVALID_CAP; + err = _process.set_parent(monitor, &mapped_parent); + + if (err) + return err; + + _monitor->set_parent(monitor, mapped_parent); + /* Obtain the filesystem capability for exporting to the task. */ l4_cap_idx_t fsserver_cap = _process.allocate_cap(); @@ -338,13 +361,13 @@ if (err) return err; - _exec_pager->add_thread(thread, mapped_thread); + _monitor->set_thread(thread, mapped_thread); return L4_EOK; } /* Start a new process for the payload indicated by the first of the given - program arguments, returning a reference to the pager as an object for - interacting with the process. */ + program arguments, returning a reference to the process monitor as an object + for interacting with the process. */ long ProcessCreating::start(int argc, const char *argv[], l4_cap_idx_t *process) { @@ -368,6 +391,8 @@ /* Initialise the different elements of the process. */ + l4_cap_idx_t pager; + err = init_region_mapper(); if (err) return err; @@ -376,23 +401,27 @@ if (err) return err; - err = init_external_pager(process); + err = init_external_pager(&pager); if (err) return err; - err = configure_task(*process); + err = init_process_monitor(process); if (err) return err; - err = create_ipc_gate(); + err = configure_task(); if (err) return err; - err = start_region_mapper(*process); + err = allocate_internal_pager(); if (err) return err; - err = start_program(argc, argv); + err = start_region_mapper(pager); + if (err) + return err; + + err = start_program(*process, argc, argv); if (err) return err; diff -r c28f4b1c2dc2 -r f2f170ce32e8 libexec/lib/src/process_monitor.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libexec/lib/src/process_monitor.cc Fri Mar 24 00:46:26 2023 +0100 @@ -0,0 +1,158 @@ +/* + * A process monitor abstraction. + * + * Copyright (C) 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 + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA + */ + +#include +#include +#include + +#include + +#include "process_monitor.h" +#include "parent_notification_object_server.h" + + + +/* A process monitor receiving signals from a task. */ + +ProcessMonitor::ProcessMonitor() +: NotificationSupport() +{ +} + +ipc_server_default_config_type ProcessMonitor::config() +{ + return config_ParentNotificationObject; +} + + + +/* Close the process monitor. */ + +void ProcessMonitor::close() +{ + printf("Process monitor closing...\n"); + + if (l4_is_valid_cap(_task)) + { + ipc_unmap_capability(_task, _mapped_task); + ipc_cap_free_um(_task); + _task = L4_INVALID_CAP; + } +} + + + +/* Capability management. */ + +void ProcessMonitor::set_pager(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) +{ + _pager = cap; + _mapped_pager = mapped_cap; +} + +void ProcessMonitor::set_parent(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) +{ + _parent = cap; + _mapped_parent = mapped_cap; +} + +void ProcessMonitor::set_task(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) +{ + _task = cap; + _mapped_task = mapped_cap; +} + +void ProcessMonitor::set_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) +{ + _thread = cap; + _mapped_thread = mapped_cap; +} + + + +/* Lifecycle management. */ + +void ProcessMonitor::pager_ended() +{ + /* Release the program thread and its reference to this object. This will + cause this object to be closed. */ + + if (l4_is_valid_cap(_thread)) + { + ipc_unmap_capability(_task, _mapped_thread); + ipc_cap_free_um(_thread); + _thread = L4_INVALID_CAP; + + ipc_unmap_capability(_task, _mapped_parent); + } +} + + + +/* Receive signals from a task. */ + +long ProcessMonitor::signal(unsigned long sig, unsigned long val) +{ + notify_all(NOTIFY_TASK_SIGNAL, (notify_values_t) {sig, val}); + + /* Handle the termination event. */ + + if (sig == 0) + { + printf("Signal from task.\n"); + + /* Once the program exits, the IPC gate connecting the program with its + internal pager can be released. This will cause the internal pager to + finish, which is then handled by the external pager. */ + + if (l4_is_valid_cap(_pager)) + { + ipc_cap_free_um(_pager); + _pager = L4_INVALID_CAP; + } + + /* The thread is not released here since the initiator of the process + needs to be able to receive a reference to this object, but if the + process terminates and the thread is released, this object may be + released before the initiator obtains a reference to it. */ + } + + return L4_EOK; +} + + + +/* Subscribe to notifications. */ + +long ProcessMonitor::subscribe(l4_cap_idx_t notifier, notify_flags_t flags) +{ + return NotificationSupport::subscribe(notifier, flags); +} + +/* Unsubscribe from notifications. */ + +long ProcessMonitor::unsubscribe(l4_cap_idx_t notifier) +{ + return NotificationSupport::unsubscribe(notifier); +} + +/* vim: tabstop=2 expandtab shiftwidth=2 +*/ diff -r c28f4b1c2dc2 -r f2f170ce32e8 libsystypes/idl/parent_notification_object.idl --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libsystypes/idl/parent_notification_object.idl Fri Mar 24 00:46:26 2023 +0100 @@ -0,0 +1,4 @@ +import "notification.idl"; +import "parent.idl"; + +interface ParentNotificationObject composes Parent, Notification;