1 /* 2 * A process monitor abstraction. 3 * 4 * Copyright (C) 2022, 2023 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <ipc/cap_alloc.h> 23 #include <ipc/map.h> 24 #include <systypes/base.h> 25 26 #include <stdio.h> 27 28 #include "process_monitor.h" 29 #include "parent_notification_object_server.h" 30 31 32 33 /* A process monitor receiving signals from a task. */ 34 35 ProcessMonitor::ProcessMonitor() 36 : NotificationSupport() 37 { 38 } 39 40 ipc_server_default_config_type ProcessMonitor::config() 41 { 42 return config_ParentNotificationObject; 43 } 44 45 46 47 /* Close the process monitor. */ 48 49 void ProcessMonitor::close() 50 { 51 printf("Process monitor closing...\n"); 52 53 if (l4_is_valid_cap(_task)) 54 { 55 ipc_unmap_capability(_task, _mapped_task); 56 ipc_cap_free_um(_task); 57 _task = L4_INVALID_CAP; 58 } 59 } 60 61 62 63 /* Capability management. */ 64 65 void ProcessMonitor::set_pager(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) 66 { 67 _pager = cap; 68 _mapped_pager = mapped_cap; 69 } 70 71 void ProcessMonitor::set_parent(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) 72 { 73 _parent = cap; 74 _mapped_parent = mapped_cap; 75 } 76 77 void ProcessMonitor::set_task(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) 78 { 79 _task = cap; 80 _mapped_task = mapped_cap; 81 } 82 83 void ProcessMonitor::set_thread(l4_cap_idx_t cap, l4_cap_idx_t mapped_cap) 84 { 85 _thread = cap; 86 _mapped_thread = mapped_cap; 87 } 88 89 90 91 /* Lifecycle management. */ 92 93 void ProcessMonitor::pager_ended() 94 { 95 /* Release the program thread and its reference to this object. This will 96 cause this object to be closed. */ 97 98 if (l4_is_valid_cap(_thread)) 99 { 100 ipc_unmap_capability(_task, _mapped_thread); 101 ipc_cap_free_um(_thread); 102 _thread = L4_INVALID_CAP; 103 104 ipc_unmap_capability(_task, _mapped_parent); 105 } 106 } 107 108 109 110 /* Receive signals from a task. */ 111 112 long ProcessMonitor::signal(unsigned long sig, unsigned long val) 113 { 114 notify_all(NOTIFY_TASK_SIGNAL, (notify_values_t) {sig, val}); 115 116 /* Handle the termination event. */ 117 118 if (sig == 0) 119 { 120 printf("Signal from task.\n"); 121 122 /* Once the program exits, the IPC gate connecting the program with its 123 internal pager can be released. This will cause the internal pager to 124 finish, which is then handled by the external pager. */ 125 126 if (l4_is_valid_cap(_pager)) 127 { 128 ipc_cap_free_um(_pager); 129 _pager = L4_INVALID_CAP; 130 } 131 132 /* The thread is not released here since the initiator of the process 133 needs to be able to receive a reference to this object, but if the 134 process terminates and the thread is released, this object may be 135 released before the initiator obtains a reference to it. */ 136 } 137 138 return L4_EOK; 139 } 140 141 142 143 /* Subscribe to notifications. */ 144 145 long ProcessMonitor::subscribe(l4_cap_idx_t notifier, notify_flags_t flags) 146 { 147 return NotificationSupport::subscribe(notifier, flags); 148 } 149 150 /* Unsubscribe from notifications. */ 151 152 long ProcessMonitor::unsubscribe(l4_cap_idx_t notifier) 153 { 154 return NotificationSupport::unsubscribe(notifier); 155 } 156 157 /* vim: tabstop=2 expandtab shiftwidth=2 158 */