source: mainline/uspace/lib/libc/generic/loader.c@ 4470e26

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 4470e26 was 4470e26, checked in by Jiri Svoboda <jirik.svoboda@…>, 17 years ago

Separate load and run commands for loader. Update tracer - no events get missed on startup anymore.

  • Property mode set to 100644
File size: 6.6 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
33 */
34
35#include <ipc/ipc.h>
36#include <ipc/loader.h>
37#include <libc.h>
38#include <string.h>
39#include <stdlib.h>
40#include <async.h>
41#include <errno.h>
42#include <vfs/vfs.h>
43#include <loader/loader.h>
44
45/** Connect to a new program loader.
46 *
47 * Spawns a new program loader task and returns the connection structure.
48 * @return Pointer to the loader connection structure (should be
49 * de-allocated using free() after use).
50 */
51loader_t *loader_spawn(void)
52{
53 int phone_id, rc;
54 loader_t *ldr;
55
56 /*
57 * Ask kernel to spawn a new loader task.
58 */
59 rc = __SYSCALL1(SYS_PROGRAM_SPAWN_LOADER, (sysarg_t) &phone_id);
60 if (rc != 0)
61 return NULL;
62
63 /*
64 * Say hello so that the loader knows the incoming connection's
65 * phone hash.
66 */
67 rc = async_req_0_0(phone_id, LOADER_HELLO);
68 if (rc != EOK)
69 return NULL;
70
71 ldr = malloc(sizeof(loader_t));
72 if (ldr == NULL)
73 return NULL;
74
75 ldr->phone_id = phone_id;
76 return ldr;
77}
78
79/** Get ID of the new task.
80 *
81 * Retrieves the ID of the new task from the loader.
82 *
83 * @param ldr Loader connection structure.
84 * @param task_id Points to a variable where the ID should be stored.
85 * @return Zero on success or negative error code.
86 */
87int loader_get_task_id(loader_t *ldr, task_id_t *task_id)
88{
89 ipc_call_t answer;
90 aid_t req;
91 int rc;
92 ipcarg_t retval;
93
94 /* Get task ID. */
95 req = async_send_0(ldr->phone_id, LOADER_GET_TASKID, &answer);
96 rc = ipc_data_read_start(ldr->phone_id, task_id, sizeof(task_id));
97 if (rc != EOK) {
98 async_wait_for(req, NULL);
99 return rc;
100 }
101
102 async_wait_for(req, &retval);
103 return (int)retval;
104}
105
106/** Set pathname of the program to load.
107 *
108 * Sets the name of the program file to load. The name can be relative
109 * to the current working directory (it will be absolutized before
110 * sending to the loader).
111 *
112 * @param ldr Loader connection structure.
113 * @param path Pathname of the program file.
114 * @return Zero on success or negative error code.
115 */
116int loader_set_pathname(loader_t *ldr, const char *path)
117{
118 ipc_call_t answer;
119 aid_t req;
120 int rc;
121 ipcarg_t retval;
122
123 char *pa;
124 size_t pa_len;
125
126 pa = absolutize(path, &pa_len);
127 if (!pa)
128 return 0;
129
130 /* Send program pathname */
131 req = async_send_0(ldr->phone_id, LOADER_SET_PATHNAME, &answer);
132 rc = ipc_data_write_start(ldr->phone_id, (void *)pa, pa_len);
133 if (rc != EOK) {
134 async_wait_for(req, NULL);
135 return rc;
136 }
137
138 free(pa);
139
140 async_wait_for(req, &retval);
141 return (int)retval;
142}
143
144
145/** Set command-line arguments for the program.
146 *
147 * Sets the vector of command-line arguments to be passed to the loaded
148 * program. By convention, the very first argument is typically the same as
149 * the command used to execute the program.
150 *
151 * @param ldr Loader connection structure.
152 * @param argv NULL-terminated array of pointers to arguments.
153 * @return Zero on success or negative error code.
154 */
155int loader_set_args(loader_t *ldr, char *const argv[])
156{
157 aid_t req;
158 ipc_call_t answer;
159 ipcarg_t rc;
160
161 char *const *ap;
162 char *dp;
163 char *arg_buf;
164 size_t buffer_size;
165
166 /*
167 * Serialize the arguments into a single array. First
168 * compute size of the buffer needed.
169 */
170 ap = argv;
171 buffer_size = 0;
172 while (*ap != NULL) {
173 buffer_size += strlen(*ap) + 1;
174 ++ap;
175 }
176
177 arg_buf = malloc(buffer_size);
178 if (arg_buf == NULL) return ENOMEM;
179
180 /* Now fill the buffer with null-terminated argument strings */
181 ap = argv;
182 dp = arg_buf;
183 while (*ap != NULL) {
184 strcpy(dp, *ap);
185 dp += strlen(*ap) + 1;
186
187 ++ap;
188 }
189
190 /* Send serialized arguments to the loader */
191
192 req = async_send_0(ldr->phone_id, LOADER_SET_ARGS, &answer);
193 rc = ipc_data_write_start(ldr->phone_id, (void *)arg_buf, buffer_size);
194 if (rc != EOK) {
195 async_wait_for(req, NULL);
196 return rc;
197 }
198
199 async_wait_for(req, &rc);
200 if (rc != EOK) return rc;
201
202 /* Free temporary buffer */
203 free(arg_buf);
204
205 return EOK;
206}
207
[4470e26]208/** Instruct loader to load the program.
209 *
210 * If this function succeeds, the program has been successfully loaded
211 * and is ready to be executed.
212 *
213 * @param ldr Loader connection structure.
214 * @return Zero on success or negative error code.
215 */
216int loader_load_program(loader_t *ldr)
217{
218 int rc;
219
220 rc = async_req_0_0(ldr->phone_id, LOADER_LOAD);
221 if (rc != EOK)
222 return rc;
223
224 return EOK;
225}
226
[45454e9b]227/** Instruct loader to execute the program.
[4470e26]228 *
229 * Note that this function blocks until the loader actually replies
230 * so you cannot expect this function to return if you are debugging
231 * the task and its thread is stopped.
[45454e9b]232 *
233 * After using this function, no further operations must be performed
234 * on the loader structure. It should be de-allocated using free().
235 *
236 * @param ldr Loader connection structure.
237 * @return Zero on success or negative error code.
238 */
[4470e26]239int loader_run(loader_t *ldr)
[45454e9b]240{
241 int rc;
242
243 rc = async_req_0_0(ldr->phone_id, LOADER_RUN);
244 if (rc != EOK)
245 return rc;
246
247 return EOK;
248}
249
250/** Cancel the loader session.
251 *
252 * Tells the loader not to load any program and terminate.
253 * After using this function, no further operations must be performed
254 * on the loader structure. It should be de-allocated using free().
255 *
256 * @param ldr Loader connection structure.
257 * @return Zero on success or negative error code.
258 */
259void loader_abort(loader_t *ldr)
260{
261 ipc_hangup(ldr->phone_id);
262 ldr->phone_id = 0;
263}
264
265/** @}
266 */
Note: See TracBrowser for help on using the repository browser.