3 * \brief startd spawn functions
7 * Copyright (c) 2010-2011, ETH Zurich.
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
15 #define _USE_XOPEN /* for strdup() in string.h */
20 #include <barrelfish/barrelfish.h>
22 #include <barrelfish/spawn_client.h>
23 #include <spawndomain/spawndomain.h>
24 #include <dist/barrier.h>
28 extern char **environ;
30 static const char *get_shortname(const char *start, const char *nameend,
34 // find the short name by searching back for the last / before the args
35 const char *shortname = nameend;
36 while (shortname >= start && *shortname != '/') {
39 if (shortname != start) {
43 // where's the end of the basename? (ie. ignoring beehive's | suffix)
44 const char *basenameend = memchr(shortname, '|', nameend - shortname);
45 if (basenameend == NULL) {
46 basenameend = nameend;
49 *namelen = basenameend - shortname;
53 static void set_local_bindings(void)
61 char *argv[MAX_CMDLINE_ARGS + 1];
70 read the next line of the bootmodule, and return info about what to
73 1: line read succesfully
74 0: end of file reached
77 static int prepare_spawn(size_t *bmpos, struct spawn_info *si)
79 assert(bmpos != NULL);
82 const char *bootmodules = gbootmodules;
84 // find the start/end of the next line
85 const char *start = &bootmodules[*bmpos];
86 const char *end = strchr(start, '\n');
90 *bmpos = end - bootmodules + 1;
93 // ignore arguments for name comparison
94 const char *args = memchr(start, ' ', end - start);
96 // where's the end of the full name?
97 const char *nameend = args == NULL ? end : args;
99 si->shortname = (char *)get_shortname(start, nameend, &si->shortnamelen);
101 si->cmdargs = malloc(end - si->shortname + 1);
102 if (si->cmdargs == NULL) {
105 si->name = malloc(nameend - start + 1);
106 if (si->name == NULL) {
111 /* Get the command line arguments of the domain: args plus shortname */
112 memcpy(si->cmdargs, si->shortname, end - si->shortname);
113 si->cmdargs[end - si->shortname] = '\0';
114 si->argc = spawn_tokenize_cmdargs(si->cmdargs, si->argv,
115 ARRAY_LENGTH(si->argv));
116 if (si->argc >= MAX_CMDLINE_ARGS) {
122 /* grab a copy of the full name as a separate string */
123 memcpy(si->name, start, nameend - start);
124 si->name[nameend - start] = '\0';
130 void spawn_dist_domains(void)
132 struct spawn_info si;
137 coreid_t my_coreid = disp_get_core_id();
141 r = prepare_spawn(&bmpos, &si);
144 } else if (r == -1) {
145 DEBUG_ERR(STARTD_ERR_BOOTMODULES,
146 "failed to read bootmodules entry");
149 /* Only spawn special dist-serv modules */
150 if (si.argc >= 2 && strcmp(si.argv[1], "dist-serv") == 0) {
156 if (si.argc >= 3 && strncmp(si.argv[2], "core=", 5) == 0) {
158 char *p = strchr(si.argv[2], '=');
160 coreid = strtol(p + 1, NULL, 10);
168 // discard 'dist-serv' and 'core=x' argument
169 for (int i = 1; i <= si.argc - extra_args; i++) {
170 si.argv[i] = si.argv[i+extra_args];
174 debug_printf("starting dist-serv %s on core %d\n", si.name, coreid);
176 struct capref new_domain;
177 err = spawn_program(coreid, si.name, si.argv, environ,
179 if (err_is_fail(err)) {
180 DEBUG_ERR(err, "spawn of %s failed", si.name);
184 char c = si.shortname[si.shortnamelen];
185 si.shortname[si.shortnamelen] = '\0';
187 // wait until fully started
188 err = nsb_wait_ready(si.shortname);
189 if (err_is_fail(err)) {
190 DEBUG_ERR(err, "nsb_wait_ready on %s failed", si.shortname);
193 si.shortname[si.shortnamelen] = c;
195 // HACK: make sure we use the local versions of a service if
196 // it was started. Really there needs to be a mechanism for that
197 // service to signal us and others to do this once it has started
199 set_local_bindings();
207 void spawn_arrakis_domains(void)
209 struct spawn_info si;
214 coreid_t my_coreid = disp_get_core_id();
218 r = prepare_spawn(&bmpos, &si);
221 } else if (r == -1) {
222 DEBUG_ERR(STARTD_ERR_BOOTMODULES,
223 "failed to read bootmodules entry");
226 /* Only spawn special arrakis modules */
227 if (si.argc >= 2 && strcmp(si.argv[1], "arrakis") == 0) {
233 if (si.argc >= 3 && strncmp(si.argv[2], "core=", 5) == 0) {
235 char *p = strchr(si.argv[2], '=');
237 coreid = strtol(p + 1, NULL, 10);
245 // discard 'dist-serv' and 'core=x' argument
246 for (int i = 1; i <= si.argc - extra_args; i++) {
247 si.argv[i] = si.argv[i+extra_args];
251 debug_printf("starting arrakis domain %s on core %d\n", si.name, coreid);
253 domainid_t new_domain;
254 err = spawn_arrakis_program(coreid, si.name, si.argv, environ,
255 NULL_CAP, NULL_CAP, 0, &new_domain);
256 if (err_is_fail(err)) {
257 DEBUG_ERR(err, "spawn of %s failed", si.name);
267 void spawn_app_domains(void)
269 struct spawn_info si;
274 coreid_t my_coreid = disp_get_core_id();
278 bool spawn_here = true;
280 r = prepare_spawn(&bmpos, &si);
283 } else if (r == -1) {
284 DEBUG_ERR(STARTD_ERR_BOOTMODULES,
285 "failed to read bootmodules entry");
288 /* Do not spawn special domains */
289 if (strncmp(si.shortname, "init", si.shortnamelen) == 0
290 || strncmp(si.shortname, "cpu", si.shortnamelen) == 0
291 // Adding following condition for cases like "cpu_omap44xx"
292 || strncmp(si.shortname, "cpu", strlen("cpu")) == 0
293 || strncmp(si.shortname, "boot_", strlen("boot_")) == 0
294 || strncmp(si.shortname, "monitor", si.shortnamelen) == 0
295 || strncmp(si.shortname, "mem_serv", si.shortnamelen) == 0
297 || strncmp(si.shortname, "corectrl", si.shortnamelen) == 0
303 /* Do not spawn special boot modules, dist-serv modules
304 or nospawn modules */
305 if (si.argc >= 2 && (strcmp(si.argv[1], "boot") == 0
306 || strcmp(si.argv[1], "dist-serv") == 0
307 || strcmp(si.argv[1], "nospawn") == 0
308 || strcmp(si.argv[1], "arrakis") == 0
309 || strcmp(si.argv[1], "auto") == 0)) {
317 uint8_t spawn_flags = 0;
318 uint8_t has_spawn_flags = 0;
319 uint8_t has_core = 0;
320 char *core_ptr = NULL;
322 for(int i = 1; i < si.argc && i < 3; ++i) {
323 if(strncmp(si.argv[i], "spawnflags=", 11) == 0) {
324 char *p = strchr(si.argv[i], '=') + 1;
325 spawn_flags = (uint8_t)strtol(p, (char **)&p, 10);
327 } else if (strncmp(si.argv[i], "core=", 5)== 0) {
328 core_ptr = strchr(si.argv[i], '=') + 1;
335 if (has_core || has_spawn_flags) {
336 for (int i = 1; i < si.argc; i++) {
337 if (has_spawn_flags && has_core) {
338 si.argv[i] = si.argv[i+2];
340 si.argv[i] = si.argv[i+1];
345 si.argc -= (has_core + has_spawn_flags);
348 while(*core_ptr != '\0') {
349 int id_from = strtol(core_ptr, (char **)&core_ptr, 10);
351 if(*core_ptr == '-') {
353 id_to = strtol(core_ptr, (char **)&core_ptr, 10);
355 assert(*core_ptr == ',' || *core_ptr == '\0');
356 if(*core_ptr != '\0') {
360 /* coreid = strtol(p + 1, NULL, 10); */
361 // discard 'core=x' argument
362 for(int i = id_from; i <= id_to; i++) {
363 debug_printf("starting app %s on core %d\n",
366 struct capref ret_domain_cap;
367 err = spawn_program(i, si.name, si.argv, environ,
368 spawn_flags, &ret_domain_cap);
369 if (err_is_fail(err)) {
370 DEBUG_ERR(err, "spawn of %s failed", si.name);
378 debug_printf("starting app %s on core %d\n", si.name, coreid);
380 struct capref ret_domain_cap;
381 err = spawn_program(coreid, si.name, si.argv, environ,
382 spawn_flags, &ret_domain_cap);
383 if (err_is_fail(err)) {
384 DEBUG_ERR(err, "spawn of %s failed", si.name);
395 void spawn_bootscript_domains(void)
398 coreid_t my_coreid = disp_get_core_id();
399 char *argv[256], *name;
401 // open bootmodules file and read it in
402 FILE *f = fopen("/bootscript", "r");
404 printf("No bootscript\n");
408 while(fgets(line, 1024, f) != NULL) {
411 // ignore comments (#) and empty lines
412 if (line[0] == '#' || line[0] == '\n') {
416 argv[0] = strtok(line, " \n");
418 for(argc = 1;; argc++) {
419 argv[argc] = strtok(NULL, " \n");
420 if(argv[argc] == NULL) {
426 if (argc >= 2 && strncmp(argv[1], "core=", 5) == 0) {
427 char *p = strchr(argv[1], '=');
432 int id_from = strtol(p, (char **)&p, 10), id_to = id_from;
435 id_to = strtol(p, (char **)&p, 10);
437 assert(*p == ',' || *p == '\0');
442 /* coreid = strtol(p + 1, NULL, 10); */
443 // discard 'core=x' argument
444 for (int i = 1; i < argc; i++) {
449 for(int i = id_from; i <= id_to; i++) {
450 debug_printf("starting app %s on core %d\n", name, i);
452 struct capref new_domain;
453 err = spawn_program(i, name, argv, environ,
455 if (err_is_fail(err)) {
456 DEBUG_ERR(err, "spawn of %s failed", name);
461 debug_printf("starting app %s on core %d\n", name, my_coreid);
463 struct capref new_domain;
464 err = spawn_program(my_coreid, name, argv, environ,
466 if (err_is_fail(err)) {
467 DEBUG_ERR(err, "spawn of %s failed", name);