1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libfsclient/lib/src/process.cc Thu Feb 23 23:49:26 2023 +0100
1.3 @@ -0,0 +1,197 @@
1.4 +/*
1.5 + * Process-related convenience functions.
1.6 + *
1.7 + * Copyright (C) 2023 Paul Boddie <paul@boddie.org.uk>
1.8 + *
1.9 + * This program is free software; you can redistribute it and/or
1.10 + * modify it under the terms of the GNU General Public License as
1.11 + * published by the Free Software Foundation; either version 2 of
1.12 + * the License, or (at your option) any later version.
1.13 + *
1.14 + * This program is distributed in the hope that it will be useful,
1.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.17 + * GNU General Public License for more details.
1.18 + *
1.19 + * You should have received a copy of the GNU General Public License
1.20 + * along with this program; if not, write to the Free Software
1.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
1.22 + * Boston, MA 02110-1301, USA
1.23 + */
1.24 +
1.25 +#include <ipc/cap_alloc.h>
1.26 +#include <ipc/mem_ipc.h>
1.27 +
1.28 +#include <stdio.h>
1.29 +#include <stdlib.h>
1.30 +
1.31 +#include "process_creator_client.h"
1.32 +
1.33 +#include "file.h"
1.34 +#include "process.h"
1.35 +#include "notifier.h"
1.36 +
1.37 +
1.38 +
1.39 +/* Create a new process object. */
1.40 +
1.41 +process_t *process_new()
1.42 +{
1.43 + process_t *process = (process_t *) malloc(sizeof(process_t));
1.44 +
1.45 + if (process == NULL)
1.46 + return NULL;
1.47 +
1.48 + process_init(process);
1.49 + return process;
1.50 +}
1.51 +
1.52 +/* Initialise the given process structure. */
1.53 +
1.54 +void process_init(process_t *process)
1.55 +{
1.56 + process->ref = L4_INVALID_CAP;
1.57 +
1.58 + /* Initialise the notifiable section of the structure. */
1.59 +
1.60 + process->notifiable.notifications = 0;
1.61 + process->notifiable.base = (notifiable_base_t *) process;
1.62 +}
1.63 +
1.64 +/* Start a process using the given file as payload.
1.65 + NOTE: This does not yet communicate arguments or obtain input/output
1.66 + pipes. */
1.67 +
1.68 +long process_start(process_t *process, file_t *file, process_notifier_t *notifier)
1.69 +{
1.70 + l4_cap_idx_t server = l4re_env_get_cap("pserver");
1.71 +
1.72 + if (l4_is_invalid_cap(server))
1.73 + return -L4_ENOMEM;
1.74 +
1.75 + /* Obtain a notification endpoint. */
1.76 +
1.77 + l4_cap_idx_t endpoint;
1.78 + long err = process_notify_get_endpoint(process, notifier, &endpoint);
1.79 +
1.80 + if (err)
1.81 + return err;
1.82 +
1.83 + /* Obtain a client for the process creator. */
1.84 +
1.85 + client_ProcessCreator creator(server);
1.86 +
1.87 + /* Start the process, supplying the given endpoint. */
1.88 +
1.89 + return creator.start(file->ref, endpoint);
1.90 +}
1.91 +
1.92 +
1.93 +
1.94 +/* NOTE: Much of the code below could be unified with the file-related
1.95 + notification code. */
1.96 +
1.97 +/* Opaque notifier type for process_notifier_t. */
1.98 +
1.99 +struct process_notifier
1.100 +{
1.101 + ObjectNotifier *obj;
1.102 +};
1.103 +
1.104 +/* Conversion to the generic notification types. */
1.105 +
1.106 +notifiable_t *process_notifiable(process_t *process)
1.107 +{
1.108 + return &process->notifiable;
1.109 +}
1.110 +
1.111 +/* Return the notification flags for a process. */
1.112 +
1.113 +notify_flags_t process_notifications(process_t *process)
1.114 +{
1.115 + return process->notifiable.notifications;
1.116 +}
1.117 +
1.118 +/* Return the notification values for a process. */
1.119 +
1.120 +notify_values_t process_notification_values(process_t *process)
1.121 +{
1.122 + return process->notifiable.values;
1.123 +}
1.124 +
1.125 +/* Close a notifier object. */
1.126 +
1.127 +void process_notify_close(process_notifier_t *notifier)
1.128 +{
1.129 + delete notifier->obj;
1.130 + delete notifier;
1.131 +}
1.132 +
1.133 +/* Obtain a local notifier object. */
1.134 +
1.135 +process_notifier_t *process_notify_local()
1.136 +{
1.137 + process_notifier_t *notifier = new process_notifier_t;
1.138 +
1.139 + notifier->obj = notifier_get_local_notifier();
1.140 + return notifier;
1.141 +}
1.142 +
1.143 +/* Obtain the task-wide notifier object. */
1.144 +
1.145 +process_notifier_t *process_notify_task()
1.146 +{
1.147 + process_notifier_t *notifier = new process_notifier_t;
1.148 +
1.149 + notifier->obj = notifier_get_task_notifier();
1.150 + return notifier;
1.151 +}
1.152 +
1.153 +/* Subscribe to notification events on a process. */
1.154 +
1.155 +long process_notify_get_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t *endpoint)
1.156 +{
1.157 + return notifier->obj->get_endpoint(process_notifiable(process), endpoint, true);
1.158 +}
1.159 +
1.160 +/* Unsubscribe from notification events on a process. */
1.161 +
1.162 +long process_notify_remove_endpoint(process_t *process, process_notifier_t *notifier, l4_cap_idx_t endpoint)
1.163 +{
1.164 + return notifier->obj->remove_endpoint(process_notifiable(process), endpoint);
1.165 +}
1.166 +
1.167 +/* Wait for a notification event on a process. */
1.168 +
1.169 +long process_notify_wait_process(process_t *process, process_notifier_t *notifier)
1.170 +{
1.171 + SpecificObjectNotifier *specific_notifier = dynamic_cast<SpecificObjectNotifier *>(notifier->obj);
1.172 + long err = specific_notifier->wait_object(process_notifiable(process));
1.173 +
1.174 + /* Unsubscribe if a closure notification has been received. */
1.175 +
1.176 + //if (!err && (process->notifiable.notifications & NOTIFY_PEER_CLOSED))
1.177 + //process_notify_unsubscribe(process, notifier);
1.178 +
1.179 + return err;
1.180 +}
1.181 +
1.182 +/* Wait for notification events on processes. */
1.183 +
1.184 +long process_notify_wait_processes(process_t **process, process_notifier_t *notifier)
1.185 +{
1.186 + GeneralObjectNotifier *general_notifier = dynamic_cast<GeneralObjectNotifier *>(notifier->obj);
1.187 + notifiable_t *notifiable;
1.188 + long err = general_notifier->wait(¬ifiable);
1.189 +
1.190 + *process = (process_t *) notifiable->base;
1.191 +
1.192 + /* Unsubscribe if a closure notification has been received. */
1.193 +
1.194 + //if (!err && ((*file)->notifiable.notifications & NOTIFY_PEER_CLOSED))
1.195 + //file_notify_unsubscribe(*file, notifier);
1.196 +
1.197 + return err;
1.198 +}
1.199 +
1.200 +// vim: tabstop=2 expandtab shiftwidth=2