source: mainline/uspace/lib/c/generic/loader.c@ fe86d9d

Last change on this file since fe86d9d was 0a8f070, checked in by Matthieu Riolo <matthieu.riolo@…>, 6 years ago

Create taskman server (extracts task-related operations from naming service)

  • Exploits initial phones connected to spawn parent instead of NS.
  • session_ns changed to session_primary (setup during taskman-loader handshake).
  • Task creation moved from NS to taskman (no clonable services anymore).
  • Other task-related operations implementation is to come (task_retval is temporarily dummy).
  • Async framework: implicit connections — create fibrils for calls that arrived through initial phone.

Conflicts:

abi/include/abi/ipc/methods.h
boot/Makefile.common
uspace/Makefile
uspace/app/trace/ipcp.c
uspace/lib/c/generic/async.c
uspace/lib/c/generic/libc.c
uspace/lib/c/generic/loader.c
uspace/lib/c/generic/ns.c
uspace/lib/c/generic/private/async.h
uspace/lib/c/generic/private/ns.h
uspace/lib/c/generic/task.c
uspace/lib/c/include/async.h
uspace/lib/c/include/ipc/services.h
uspace/lib/c/include/ipc/taskman.h
uspace/lib/c/include/loader/pcb.h
uspace/lib/c/include/ns.h
uspace/srv/loader/main.c
uspace/srv/ns/clonable.c
uspace/srv/ns/ns.c

  • Property mode set to 100644
File size: 8.7 KB
RevLine 
[45454e9b]1/*
2 * Copyright (c) 2008 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
[937aeee]33 */
[45454e9b]34
[0a8f070]35#include <async.h>
36#include <errno.h>
[45454e9b]37#include <ipc/loader.h>
[bfd1546]38#include <ipc/services.h>
[0a8f070]39#include <ipc/taskman.h>
[45454e9b]40#include <libc.h>
[0a8f070]41#include <loader/loader.h>
42#include <ns.h>
[45454e9b]43#include <stdlib.h>
[0a8f070]44#include <str.h>
45#include <task.h>
[45454e9b]46#include <vfs/vfs.h>
[79ae36dd]47#include "private/loader.h"
[45454e9b]48
49/** Connect to a new program loader.
50 *
51 * Spawns a new program loader task and returns the connection structure.
[937aeee]52 *
53 * @param name Symbolic name to set on the newly created task.
54 *
[f77c1c9]55 * @return Error code.
[45454e9b]56 */
[b7fd2a0]57errno_t loader_spawn(const char *name)
[45454e9b]58{
[b7fd2a0]59 return (errno_t) __SYSCALL2(SYS_PROGRAM_SPAWN_LOADER,
[9eb3623]60 (sysarg_t) name, str_size(name));
[bfd1546]61}
[45454e9b]62
[bfd1546]63loader_t *loader_connect(void)
64{
[937aeee]65 loader_t *ldr = malloc(sizeof(loader_t));
[45454e9b]66 if (ldr == NULL)
67 return NULL;
[a35b458]68
[79ae36dd]69 async_sess_t *sess =
[0a8f070]70 service_connect_blocking(SERVICE_TASKMAN, TASKMAN_CONNECT_TO_LOADER, 0);
[79ae36dd]71 if (sess == NULL) {
72 free(ldr);
73 return NULL;
74 }
[a35b458]75
[79ae36dd]76 ldr->sess = sess;
[937aeee]77 return ldr;
[45454e9b]78}
79
80/** Get ID of the new task.
81 *
82 * Retrieves the ID of the new task from the loader.
83 *
[937aeee]84 * @param ldr Loader connection structure.
85 * @param task_id Points to a variable where the ID should be stored.
86 *
[cde999a]87 * @return Zero on success or an error code.
[937aeee]88 *
[45454e9b]89 */
[b7fd2a0]90errno_t loader_get_task_id(loader_t *ldr, task_id_t *task_id)
[45454e9b]91{
92 /* Get task ID. */
[79ae36dd]93 async_exch_t *exch = async_exchange_begin(ldr->sess);
[a35b458]94
[937aeee]95 ipc_call_t answer;
[79ae36dd]96 aid_t req = async_send_0(exch, LOADER_GET_TASKID, &answer);
[b7fd2a0]97 errno_t rc = async_data_read_start(exch, task_id, sizeof(task_id_t));
[a35b458]98
[79ae36dd]99 async_exchange_end(exch);
[a35b458]100
[45454e9b]101 if (rc != EOK) {
[50b581d]102 async_forget(req);
[b7fd2a0]103 return (errno_t) rc;
[45454e9b]104 }
[a35b458]105
[79ae36dd]106 async_wait_for(req, &rc);
[b7fd2a0]107 return (errno_t) rc;
[45454e9b]108}
109
[622cdbe]110/** Set current working directory for the loaded task.
111 *
112 * Sets the current working directory for the loaded task.
113 *
114 * @param ldr Loader connection structure.
115 *
[cde999a]116 * @return Zero on success or an error code.
[622cdbe]117 *
118 */
[b7fd2a0]119errno_t loader_set_cwd(loader_t *ldr)
[622cdbe]120{
[79ae36dd]121 char *cwd = (char *) malloc(MAX_PATH_LEN + 1);
[622cdbe]122 if (!cwd)
123 return ENOMEM;
[a35b458]124
[d96d9bc]125 if (vfs_cwd_get(cwd, MAX_PATH_LEN + 1) != EOK)
[79ae36dd]126 str_cpy(cwd, MAX_PATH_LEN + 1, "/");
[a35b458]127
[79ae36dd]128 size_t len = str_length(cwd);
[a35b458]129
[79ae36dd]130 async_exch_t *exch = async_exchange_begin(ldr->sess);
[a35b458]131
[622cdbe]132 ipc_call_t answer;
[79ae36dd]133 aid_t req = async_send_0(exch, LOADER_SET_CWD, &answer);
[b7fd2a0]134 errno_t rc = async_data_write_start(exch, cwd, len);
[a35b458]135
[79ae36dd]136 async_exchange_end(exch);
[622cdbe]137 free(cwd);
[a35b458]138
[622cdbe]139 if (rc != EOK) {
[50b581d]140 async_forget(req);
[b7fd2a0]141 return (errno_t) rc;
[622cdbe]142 }
[a35b458]143
[79ae36dd]144 async_wait_for(req, &rc);
[b7fd2a0]145 return (errno_t) rc;
[622cdbe]146}
147
[bb9ec2d]148/** Set the program to load.
[45454e9b]149 *
[937aeee]150 * @param ldr Loader connection structure.
[bb9ec2d]151 * @param name Name to set for the spawned program.
152 * @param file Program file.
[937aeee]153 *
[cde999a]154 * @return Zero on success or an error code.
[937aeee]155 *
[45454e9b]156 */
[b7fd2a0]157errno_t loader_set_program(loader_t *ldr, const char *name, int file)
[45454e9b]158{
[79ae36dd]159 async_exch_t *exch = async_exchange_begin(ldr->sess);
[bb9ec2d]160
[937aeee]161 ipc_call_t answer;
[bb9ec2d]162 aid_t req = async_send_0(exch, LOADER_SET_PROGRAM, &answer);
163
[b7fd2a0]164 errno_t rc = async_data_write_start(exch, name, str_size(name) + 1);
[bb9ec2d]165 if (rc == EOK) {
166 async_exch_t *vfs_exch = vfs_exchange_begin();
167 rc = vfs_pass_handle(vfs_exch, file, exch);
168 vfs_exchange_end(vfs_exch);
169 }
170
[79ae36dd]171 async_exchange_end(exch);
[bb9ec2d]172
[45454e9b]173 if (rc != EOK) {
[50b581d]174 async_forget(req);
[b7fd2a0]175 return (errno_t) rc;
[45454e9b]176 }
[bb9ec2d]177
[79ae36dd]178 async_wait_for(req, &rc);
[b7fd2a0]179 return (errno_t) rc;
[45454e9b]180}
181
[bb9ec2d]182/** Set the program to load by path.
183 *
184 * @param ldr Loader connection structure.
185 * @param path Program path.
186 *
[cde999a]187 * @return Zero on success or an error code.
[bb9ec2d]188 *
189 */
[b7fd2a0]190errno_t loader_set_program_path(loader_t *ldr, const char *path)
[bb9ec2d]191{
[9286475]192 size_t abslen;
193 char *abspath = vfs_absolutize(path, &abslen);
194 if (!abspath)
195 return ENOMEM;
[a35b458]196
[f77c1c9]197 int fd;
[b7fd2a0]198 errno_t rc = vfs_lookup(path, 0, &fd);
[f77c1c9]199 if (rc != EOK) {
200 return rc;
[bb9ec2d]201 }
[a35b458]202
[21d3201]203 rc = loader_set_program(ldr, abspath, fd);
[9c4cf0d]204 vfs_put(fd);
[bb9ec2d]205 return rc;
206}
207
[45454e9b]208/** Set command-line arguments for the program.
209 *
210 * Sets the vector of command-line arguments to be passed to the loaded
211 * program. By convention, the very first argument is typically the same as
212 * the command used to execute the program.
213 *
[937aeee]214 * @param ldr Loader connection structure.
215 * @param argv NULL-terminated array of pointers to arguments.
216 *
[cde999a]217 * @return Zero on success or an error code.
[937aeee]218 *
[45454e9b]219 */
[b7fd2a0]220errno_t loader_set_args(loader_t *ldr, const char *const argv[])
[45454e9b]221{
[937aeee]222 /*
[45454e9b]223 * Serialize the arguments into a single array. First
224 * compute size of the buffer needed.
225 */
[a000878c]226 const char *const *ap = argv;
[937aeee]227 size_t buffer_size = 0;
[45454e9b]228 while (*ap != NULL) {
[9eb3623]229 buffer_size += str_size(*ap) + 1;
[937aeee]230 ap++;
[45454e9b]231 }
[a35b458]232
[937aeee]233 char *arg_buf = malloc(buffer_size);
234 if (arg_buf == NULL)
235 return ENOMEM;
[a35b458]236
[45454e9b]237 /* Now fill the buffer with null-terminated argument strings */
238 ap = argv;
[937aeee]239 char *dp = arg_buf;
[a35b458]240
[45454e9b]241 while (*ap != NULL) {
[6eb2e96]242 str_cpy(dp, buffer_size - (dp - arg_buf), *ap);
[9eb3623]243 dp += str_size(*ap) + 1;
[937aeee]244 ap++;
[45454e9b]245 }
[a35b458]246
[45454e9b]247 /* Send serialized arguments to the loader */
[79ae36dd]248 async_exch_t *exch = async_exchange_begin(ldr->sess);
[a35b458]249
[937aeee]250 ipc_call_t answer;
[79ae36dd]251 aid_t req = async_send_0(exch, LOADER_SET_ARGS, &answer);
[b7fd2a0]252 errno_t rc = async_data_write_start(exch, (void *) arg_buf,
[79ae36dd]253 buffer_size);
[a35b458]254
[79ae36dd]255 async_exchange_end(exch);
256 free(arg_buf);
[a35b458]257
[45454e9b]258 if (rc != EOK) {
[50b581d]259 async_forget(req);
[b7fd2a0]260 return (errno_t) rc;
[45454e9b]261 }
[a35b458]262
[45454e9b]263 async_wait_for(req, &rc);
[b7fd2a0]264 return (errno_t) rc;
[937aeee]265}
[45454e9b]266
[bb9ec2d]267/** Add a file to the task's inbox.
[937aeee]268 *
[bb9ec2d]269 * @param ldr Loader connection structure.
270 * @param name Identification of the file.
271 * @param file The file's descriptor.
[937aeee]272 *
[cde999a]273 * @return Zero on success or an error code.
[937aeee]274 *
275 */
[b7fd2a0]276errno_t loader_add_inbox(loader_t *ldr, const char *name, int file)
[937aeee]277{
[79ae36dd]278 async_exch_t *exch = async_exchange_begin(ldr->sess);
[7171760]279 async_exch_t *vfs_exch = vfs_exchange_begin();
[a35b458]280
[bb9ec2d]281 aid_t req = async_send_0(exch, LOADER_ADD_INBOX, NULL);
[a35b458]282
[b7fd2a0]283 errno_t rc = async_data_write_start(exch, name, str_size(name) + 1);
[bb9ec2d]284 if (rc == EOK) {
285 rc = vfs_pass_handle(vfs_exch, file, exch);
[7171760]286 }
[a35b458]287
[bb9ec2d]288 async_exchange_end(vfs_exch);
[7171760]289 async_exchange_end(exch);
[a35b458]290
[bb9ec2d]291 if (rc == EOK) {
292 async_wait_for(req, &rc);
293 } else {
[50b581d]294 async_forget(req);
[937aeee]295 }
[a35b458]296
[b7fd2a0]297 return (errno_t) rc;
[45454e9b]298}
299
[4470e26]300/** Instruct loader to load the program.
301 *
302 * If this function succeeds, the program has been successfully loaded
303 * and is ready to be executed.
304 *
[937aeee]305 * @param ldr Loader connection structure.
306 *
[cde999a]307 * @return Zero on success or an error code.
[937aeee]308 *
[4470e26]309 */
[b7fd2a0]310errno_t loader_load_program(loader_t *ldr)
[4470e26]311{
[79ae36dd]312 async_exch_t *exch = async_exchange_begin(ldr->sess);
[b7fd2a0]313 errno_t rc = async_req_0_0(exch, LOADER_LOAD);
[79ae36dd]314 async_exchange_end(exch);
[a35b458]315
[79ae36dd]316 return rc;
[4470e26]317}
318
[45454e9b]319/** Instruct loader to execute the program.
[4470e26]320 *
321 * Note that this function blocks until the loader actually replies
322 * so you cannot expect this function to return if you are debugging
323 * the task and its thread is stopped.
[45454e9b]324 *
[79ae36dd]325 * After using this function, no further operations can be performed
326 * on the loader structure and it is deallocated.
[45454e9b]327 *
[937aeee]328 * @param ldr Loader connection structure.
329 *
[cde999a]330 * @return Zero on success or an error code.
[937aeee]331 *
[45454e9b]332 */
[b7fd2a0]333errno_t loader_run(loader_t *ldr)
[45454e9b]334{
[79ae36dd]335 async_exch_t *exch = async_exchange_begin(ldr->sess);
[b7fd2a0]336 errno_t rc = async_req_0_0(exch, LOADER_RUN);
[79ae36dd]337 async_exchange_end(exch);
[a35b458]338
[45454e9b]339 if (rc != EOK)
340 return rc;
[a35b458]341
[79ae36dd]342 async_hangup(ldr->sess);
343 free(ldr);
[a35b458]344
[45454e9b]345 return EOK;
346}
347
348/** Cancel the loader session.
349 *
[79ae36dd]350 * Tell the loader not to load any program and terminate.
351 * After using this function, no further operations can be performed
352 * on the loader structure and it is deallocated.
[45454e9b]353 *
[937aeee]354 * @param ldr Loader connection structure.
355 *
[cde999a]356 * @return Zero on success or an error code.
[937aeee]357 *
[45454e9b]358 */
359void loader_abort(loader_t *ldr)
360{
[79ae36dd]361 async_hangup(ldr->sess);
362 free(ldr);
[45454e9b]363}
364
365/** @}
366 */
Note: See TracBrowser for help on using the repository browser.