paul@483 | 1 | /* |
paul@483 | 2 | * Process-related convenience functions. |
paul@483 | 3 | * |
paul@483 | 4 | * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk> |
paul@483 | 5 | * |
paul@483 | 6 | * This program is free software; you can redistribute it and/or |
paul@483 | 7 | * modify it under the terms of the GNU General Public License as |
paul@483 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@483 | 9 | * the License, or (at your option) any later version. |
paul@483 | 10 | * |
paul@483 | 11 | * This program is distributed in the hope that it will be useful, |
paul@483 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@483 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@483 | 14 | * GNU General Public License for more details. |
paul@483 | 15 | * |
paul@483 | 16 | * You should have received a copy of the GNU General Public License |
paul@483 | 17 | * along with this program; if not, write to the Free Software |
paul@483 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@483 | 19 | * Boston, MA 02110-1301, USA |
paul@483 | 20 | */ |
paul@483 | 21 | |
paul@483 | 22 | #include <ipc/cap_alloc.h> |
paul@483 | 23 | #include <ipc/mem_ipc.h> |
paul@483 | 24 | |
paul@483 | 25 | #include <stdio.h> |
paul@483 | 26 | #include <stdlib.h> |
paul@483 | 27 | |
paul@483 | 28 | #include "process_creator_client.h" |
paul@483 | 29 | |
paul@483 | 30 | #include "file.h" |
paul@483 | 31 | #include "process.h" |
paul@483 | 32 | #include "notifier.h" |
paul@483 | 33 | |
paul@483 | 34 | |
paul@483 | 35 | |
paul@483 | 36 | /* Create a new process object. */ |
paul@483 | 37 | |
paul@483 | 38 | process_t *process_new() |
paul@483 | 39 | { |
paul@483 | 40 | process_t *process = (process_t *) malloc(sizeof(process_t)); |
paul@483 | 41 | |
paul@483 | 42 | if (process == NULL) |
paul@483 | 43 | return NULL; |
paul@483 | 44 | |
paul@483 | 45 | process_init(process); |
paul@483 | 46 | return process; |
paul@483 | 47 | } |
paul@483 | 48 | |
paul@483 | 49 | /* Initialise the given process structure. */ |
paul@483 | 50 | |
paul@483 | 51 | void process_init(process_t *process) |
paul@483 | 52 | { |
paul@483 | 53 | process->ref = L4_INVALID_CAP; |
paul@483 | 54 | |
paul@483 | 55 | /* Initialise the notifiable section of the structure. */ |
paul@483 | 56 | |
paul@483 | 57 | process->notifiable.notifications = 0; |
paul@483 | 58 | process->notifiable.base = (notifiable_base_t *) process; |
paul@483 | 59 | } |
paul@483 | 60 | |
paul@483 | 61 | /* Start a process using the given file as payload. |
paul@483 | 62 | NOTE: This does not yet communicate arguments or obtain input/output |
paul@483 | 63 | pipes. */ |
paul@483 | 64 | |
paul@484 | 65 | long process_start(process_t *process, file_t *file) |
paul@483 | 66 | { |
paul@483 | 67 | l4_cap_idx_t server = l4re_env_get_cap("pserver"); |
paul@483 | 68 | |
paul@483 | 69 | if (l4_is_invalid_cap(server)) |
paul@483 | 70 | return -L4_ENOMEM; |
paul@483 | 71 | |
paul@483 | 72 | /* Obtain a client for the process creator. */ |
paul@483 | 73 | |
paul@483 | 74 | client_ProcessCreator creator(server); |
paul@483 | 75 | |
paul@484 | 76 | /* Start the process, obtaining a reference to it. */ |
paul@483 | 77 | |
paul@484 | 78 | return creator.start(file->ref, &process->ref); |
paul@483 | 79 | } |
paul@483 | 80 | |
paul@483 | 81 | |
paul@483 | 82 | |
paul@483 | 83 | /* NOTE: Much of the code below could be unified with the file-related |
paul@483 | 84 | notification code. */ |
paul@483 | 85 | |
paul@483 | 86 | /* Opaque notifier type for process_notifier_t. */ |
paul@483 | 87 | |
paul@483 | 88 | struct process_notifier |
paul@483 | 89 | { |
paul@483 | 90 | ObjectNotifier *obj; |
paul@483 | 91 | }; |
paul@483 | 92 | |
paul@483 | 93 | /* Conversion to the generic notification types. */ |
paul@483 | 94 | |
paul@483 | 95 | notifiable_t *process_notifiable(process_t *process) |
paul@483 | 96 | { |
paul@483 | 97 | return &process->notifiable; |
paul@483 | 98 | } |
paul@483 | 99 | |
paul@483 | 100 | /* Return the notification flags for a process. */ |
paul@483 | 101 | |
paul@483 | 102 | notify_flags_t process_notifications(process_t *process) |
paul@483 | 103 | { |
paul@483 | 104 | return process->notifiable.notifications; |
paul@483 | 105 | } |
paul@483 | 106 | |
paul@483 | 107 | /* Return the notification values for a process. */ |
paul@483 | 108 | |
paul@483 | 109 | notify_values_t process_notification_values(process_t *process) |
paul@483 | 110 | { |
paul@483 | 111 | return process->notifiable.values; |
paul@483 | 112 | } |
paul@483 | 113 | |
paul@483 | 114 | /* Close a notifier object. */ |
paul@483 | 115 | |
paul@483 | 116 | void process_notify_close(process_notifier_t *notifier) |
paul@483 | 117 | { |
paul@483 | 118 | delete notifier->obj; |
paul@483 | 119 | delete notifier; |
paul@483 | 120 | } |
paul@483 | 121 | |
paul@483 | 122 | /* Obtain a local notifier object. */ |
paul@483 | 123 | |
paul@483 | 124 | process_notifier_t *process_notify_local() |
paul@483 | 125 | { |
paul@483 | 126 | process_notifier_t *notifier = new process_notifier_t; |
paul@483 | 127 | |
paul@483 | 128 | notifier->obj = notifier_get_local_notifier(); |
paul@483 | 129 | return notifier; |
paul@483 | 130 | } |
paul@483 | 131 | |
paul@483 | 132 | /* Obtain the task-wide notifier object. */ |
paul@483 | 133 | |
paul@483 | 134 | process_notifier_t *process_notify_task() |
paul@483 | 135 | { |
paul@483 | 136 | process_notifier_t *notifier = new process_notifier_t; |
paul@483 | 137 | |
paul@483 | 138 | notifier->obj = notifier_get_task_notifier(); |
paul@483 | 139 | return notifier; |
paul@483 | 140 | } |
paul@483 | 141 | |
paul@483 | 142 | /* Subscribe to notification events on a process. */ |
paul@483 | 143 | |
paul@484 | 144 | long process_notify_subscribe(process_t *process, notify_flags_t flags, process_notifier_t *notifier) |
paul@483 | 145 | { |
paul@484 | 146 | return notifier->obj->subscribe(process_notifiable(process), flags); |
paul@483 | 147 | } |
paul@483 | 148 | |
paul@483 | 149 | /* Unsubscribe from notification events on a process. */ |
paul@483 | 150 | |
paul@484 | 151 | long process_notify_unsubscribe(process_t *process, process_notifier_t *notifier) |
paul@483 | 152 | { |
paul@484 | 153 | return notifier->obj->unsubscribe(process_notifiable(process)); |
paul@483 | 154 | } |
paul@483 | 155 | |
paul@483 | 156 | /* Wait for a notification event on a process. */ |
paul@483 | 157 | |
paul@483 | 158 | long process_notify_wait_process(process_t *process, process_notifier_t *notifier) |
paul@483 | 159 | { |
paul@483 | 160 | SpecificObjectNotifier *specific_notifier = dynamic_cast<SpecificObjectNotifier *>(notifier->obj); |
paul@483 | 161 | long err = specific_notifier->wait_object(process_notifiable(process)); |
paul@483 | 162 | |
paul@484 | 163 | /* Unsubscribe if a termination notification has been received. */ |
paul@483 | 164 | |
paul@484 | 165 | if (!err && (process->notifiable.notifications & NOTIFY_TASK_SIGNAL) && |
paul@484 | 166 | (process->notifiable.values.sig == 0)) |
paul@484 | 167 | process_notify_unsubscribe(process, notifier); |
paul@483 | 168 | |
paul@483 | 169 | return err; |
paul@483 | 170 | } |
paul@483 | 171 | |
paul@483 | 172 | /* Wait for notification events on processes. */ |
paul@483 | 173 | |
paul@483 | 174 | long process_notify_wait_processes(process_t **process, process_notifier_t *notifier) |
paul@483 | 175 | { |
paul@483 | 176 | GeneralObjectNotifier *general_notifier = dynamic_cast<GeneralObjectNotifier *>(notifier->obj); |
paul@483 | 177 | notifiable_t *notifiable; |
paul@483 | 178 | long err = general_notifier->wait(¬ifiable); |
paul@483 | 179 | |
paul@483 | 180 | *process = (process_t *) notifiable->base; |
paul@483 | 181 | |
paul@484 | 182 | /* Unsubscribe if a termination notification has been received. */ |
paul@483 | 183 | |
paul@484 | 184 | if (!err && ((*process)->notifiable.notifications & NOTIFY_TASK_SIGNAL) && |
paul@484 | 185 | ((*process)->notifiable.values.sig == 0)) |
paul@484 | 186 | process_notify_unsubscribe(*process, notifier); |
paul@483 | 187 | |
paul@483 | 188 | return err; |
paul@483 | 189 | } |
paul@483 | 190 | |
paul@483 | 191 | // vim: tabstop=2 expandtab shiftwidth=2 |