1 /* 2 * Process-related convenience functions. 3 * 4 * Copyright (C) 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/mem_ipc.h> 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 28 #include "process_creator_client.h" 29 30 #include "file.h" 31 #include "process.h" 32 #include "notifier.h" 33 34 35 36 /* Create a new process object. */ 37 38 process_t *process_new() 39 { 40 process_t *process = (process_t *) malloc(sizeof(process_t)); 41 42 if (process == NULL) 43 return NULL; 44 45 process_init(process); 46 return process; 47 } 48 49 /* Initialise the given process structure. */ 50 51 void process_init(process_t *process) 52 { 53 process->ref = L4_INVALID_CAP; 54 55 /* Initialise the notifiable section of the structure. */ 56 57 process->notifiable.notifications = 0; 58 process->notifiable.base = (notifiable_base_t *) process; 59 } 60 61 /* Start a process using the given file as payload. 62 NOTE: This does not yet communicate arguments or obtain input/output 63 pipes. */ 64 65 long process_start(process_t *process, file_t *file, process_notifier_t *notifier) 66 { 67 l4_cap_idx_t server = l4re_env_get_cap("pserver"); 68 69 if (l4_is_invalid_cap(server)) 70 return -L4_ENOMEM; 71 72 /* Obtain a notification endpoint. */ 73 74 l4_cap_idx_t endpoint; 75 long err = process_notify_get_endpoint(process, notifier, &endpoint); 76 77 if (err) 78 return err; 79 80 /* Obtain a client for the process creator. */ 81 82 client_ProcessCreator creator(server); 83 84 /* Start the process, supplying the given endpoint. */ 85 86 return creator.start(file->ref, endpoint); 87 } 88 89 90 91 /* NOTE: Much of the code below could be unified with the file-related 92 notification code. */ 93 94 /* Opaque notifier type for process_notifier_t. */ 95 96 struct process_notifier 97 { 98 ObjectNotifier *obj; 99 }; 100 101 /* Conversion to the generic notification types. */ 102 103 notifiable_t *process_notifiable(process_t *process) 104 { 105 return &process->notifiable; 106 } 107 108 /* Return the notification flags for a process. */ 109 110 notify_flags_t process_notifications(process_t *process) 111 { 112 return process->notifiable.notifications; 113 } 114 115 /* Return the notification values for a process. */ 116 117 notify_values_t process_notification_values(process_t *process) 118 { 119 return process->notifiable.values; 120 } 121 122 /* Close a notifier object. */ 123 124 void process_notify_close(process_notifier_t *notifier) 125 { 126 delete notifier->obj; 127 delete notifier; 128 } 129 130 /* Obtain a local notifier object. */ 131 132 process_notifier_t *process_notify_local() 133 { 134 process_notifier_t *notifier = new process_notifier_t; 135 136 notifier->obj = notifier_get_local_notifier(); 137 return notifier; 138 } 139 140 /* Obtain the task-wide notifier object. */ 141 142 process_notifier_t *process_notify_task() 143 { 144 process_notifier_t *notifier = new process_notifier_t; 145 146 notifier->obj = notifier_get_task_notifier(); 147 return notifier; 148 } 149 150 /* Subscribe to notification events on a process. */ 151 152 long process_notify_get_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t *endpoint) 153 { 154 return notifier->obj->get_endpoint(process_notifiable(process), endpoint, true); 155 } 156 157 /* Unsubscribe from notification events on a process. */ 158 159 long process_notify_remove_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t endpoint) 160 { 161 return notifier->obj->remove_endpoint(process_notifiable(process), endpoint); 162 } 163 164 /* Wait for a notification event on a process. */ 165 166 long process_notify_wait_process(process_t *process, process_notifier_t *notifier) 167 { 168 SpecificObjectNotifier *specific_notifier = dynamic_cast<SpecificObjectNotifier *>(notifier->obj); 169 long err = specific_notifier->wait_object(process_notifiable(process)); 170 171 /* Unsubscribe if a closure notification has been received. */ 172 173 //if (!err && (process->notifiable.notifications & NOTIFY_PEER_CLOSED)) 174 //process_notify_unsubscribe(process, notifier); 175 176 return err; 177 } 178 179 /* Wait for notification events on processes. */ 180 181 long process_notify_wait_processes(process_t **process, process_notifier_t *notifier) 182 { 183 GeneralObjectNotifier *general_notifier = dynamic_cast<GeneralObjectNotifier *>(notifier->obj); 184 notifiable_t *notifiable; 185 long err = general_notifier->wait(¬ifiable); 186 187 *process = (process_t *) notifiable->base; 188 189 /* Unsubscribe if a closure notification has been received. */ 190 191 //if (!err && ((*file)->notifiable.notifications & NOTIFY_PEER_CLOSED)) 192 //file_notify_unsubscribe(*file, notifier); 193 194 return err; 195 } 196 197 // vim: tabstop=2 expandtab shiftwidth=2