Changeset c98e6ee in mainline for uspace/lib/libc/generic/task.c


Ignore:
Timestamp:
2008-07-08T16:05:45Z (16 years ago)
Author:
Jiri Svoboda <jirik.svoboda@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
f93f168
Parents:
b7f9087
Message:

Merge program-loader related stuff from dynload branch to trunk. (huge)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/libc/generic/task.c

    rb7f9087 rc98e6ee  
    11/*
    22 * Copyright (c) 2006 Jakub Jermar
     3 * Copyright (c) 2008 Jiri Svoboda
    34 * All rights reserved.
    45 *
     
    3435
    3536#include <task.h>
     37#include <ipc/ipc.h>
     38#include <ipc/loader.h>
    3639#include <libc.h>
     40#include <string.h>
     41#include <stdlib.h>
     42#include <async.h>
     43#include <errno.h>
    3744
    3845task_id_t task_get_id(void)
     
    4552}
    4653
    47 int task_spawn(void *image, size_t size)
     54static int task_spawn_loader(void)
    4855{
    49         return __SYSCALL2(SYS_TASK_SPAWN, (sysarg_t) image, (sysarg_t) size);
     56        int phone_id, rc;
     57
     58        rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
     59        if (rc != 0)
     60                return rc;
     61
     62        return phone_id;
     63}
     64
     65static int loader_set_args(int phone_id, const char *argv[])
     66{
     67        aid_t req;
     68        ipc_call_t answer;
     69        ipcarg_t rc;
     70
     71        const char **ap;
     72        char *dp;
     73        char *arg_buf;
     74        size_t buffer_size;
     75        size_t len;
     76
     77        /*
     78         * Serialize the arguments into a single array. First
     79         * compute size of the buffer needed.
     80         */
     81        ap = argv;
     82        buffer_size = 0;
     83        while (*ap != NULL) {
     84                buffer_size += strlen(*ap) + 1;
     85                ++ap;
     86        }
     87
     88        arg_buf = malloc(buffer_size);
     89        if (arg_buf == NULL) return ENOMEM;
     90
     91        /* Now fill the buffer with null-terminated argument strings */
     92        ap = argv;
     93        dp = arg_buf;
     94        while (*ap != NULL) {
     95                strcpy(dp, *ap);
     96                dp += strlen(*ap) + 1;
     97
     98                ++ap;
     99        }
     100
     101        /* Send serialized arguments to the loader */
     102
     103        req = async_send_0(phone_id, LOADER_SET_ARGS, &answer);
     104        rc = ipc_data_write_start(phone_id, (void *)arg_buf, buffer_size);
     105        if (rc != EOK) {
     106                async_wait_for(req, NULL);
     107                return rc;
     108        }
     109
     110        async_wait_for(req, &rc);
     111        if (rc != EOK) return rc;
     112
     113        /* Free temporary buffer */
     114        free(arg_buf);
     115
     116        return EOK;
     117}
     118
     119/** Create a new task by running an executable from VFS.
     120 *
     121 * @param path  pathname of the binary to execute
     122 * @param argv  command-line arguments
     123 * @return      ID of the newly created task or zero on error.
     124 */
     125task_id_t task_spawn(const char *path, const char *argv[])
     126{
     127        int phone_id;
     128        ipc_call_t answer;
     129        aid_t req;
     130        int rc;
     131        ipcarg_t retval;
     132
     133        /* Spawn a program loader */   
     134        phone_id = task_spawn_loader();
     135        if (phone_id < 0) return 0;
     136
     137        /*
     138         * Say hello so that the loader knows the incoming connection's
     139         * phone hash.
     140         */
     141        rc = async_req_0_0(phone_id, LOADER_HELLO);
     142        if (rc != EOK) return 0;
     143
     144        /* Send program pathname */
     145        req = async_send_0(phone_id, LOADER_SET_PATHNAME, &answer);
     146        rc = ipc_data_write_start(phone_id, (void *)path, strlen(path));
     147        if (rc != EOK) {
     148                async_wait_for(req, NULL);
     149                return 1;
     150        }
     151
     152        async_wait_for(req, &retval);
     153        if (retval != EOK) goto error;
     154
     155        /* Send arguments */
     156        rc = loader_set_args(phone_id, argv);
     157        if (rc != EOK) goto error;
     158
     159        /* Request loader to start the program */       
     160        rc = async_req_0_0(phone_id, LOADER_RUN);
     161        if (rc != EOK) goto error;
     162
     163        /* Success */
     164        ipc_hangup(phone_id);
     165        return 1;
     166
     167        /* Error exit */
     168error:
     169        ipc_hangup(phone_id);
     170        return 0;
    50171}
    51172
Note: See TracChangeset for help on using the changeset viewer.