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 <barrelfish/proc_mgmt_client.h>
25 #include <dist/barrier.h>
29 extern char **environ;
31 static const char *get_shortname(const char *start, const char *nameend,
35 // find the short name by searching back for the last / before the args
36 const char *shortname = nameend;
37 while (shortname >= start && *shortname != '/') {
40 if (shortname != start) {
44 // where's the end of the basename? (ie. ignoring beehive's | suffix)
45 const char *basenameend = memchr(shortname, '|', nameend - shortname);
46 if (basenameend == NULL) {
47 basenameend = nameend;
50 *namelen = basenameend - shortname;
54 static void set_local_bindings(void)
62 char *argv[MAX_CMDLINE_ARGS + 1];
71 read the next line of the bootmodule, and return info about what to
74 1: line read succesfully
75 0: end of file reached
78 static int prepare_spawn(size_t *bmpos, struct spawn_info *si)
80 assert(bmpos != NULL);
83 const char *bootmodules = gbootmodules;
85 // find the start/end of the next line
86 const char *start = &bootmodules[*bmpos];
87 const char *end = strchr(start, '\n');
91 *bmpos = end - bootmodules + 1;
94 // ignore arguments for name comparison
95 const char *args = memchr(start, ' ', end - start);
97 // where's the end of the full name?
98 const char *nameend = args == NULL ? end : args;
100 si->shortname = (char *)get_shortname(start, nameend, &si->shortnamelen);
102 si->cmdargs = malloc(end - si->shortname + 1);
103 if (si->cmdargs == NULL) {
106 si->name = malloc(nameend - start + 1);
107 if (si->name == NULL) {
112 /* Get the command line arguments of the domain: args plus shortname */
113 memcpy(si->cmdargs, si->shortname, end - si->shortname);
114 si->cmdargs[end - si->shortname] = '\0';
115 si->argc = spawn_tokenize_cmdargs(si->cmdargs, si->argv,
116 ARRAY_LENGTH(si->argv));
117 if (si->argc >= MAX_CMDLINE_ARGS) {
123 /* grab a copy of the full name as a separate string */
124 memcpy(si->name, start, nameend - start);
125 si->name[nameend - start] = '\0';
131 void spawn_dist_domains(void)
133 struct spawn_info si;
138 coreid_t my_coreid = disp_get_core_id();
142 r = prepare_spawn(&bmpos, &si);
145 } else if (r == -1) {
146 DEBUG_ERR(STARTD_ERR_BOOTMODULES,
147 "failed to read bootmodules entry");
150 /* Only spawn special dist-serv modules */
151 if (si.argc >= 2 && strcmp(si.argv[1], "dist-serv") == 0) {
157 if (si.argc >= 3 && strncmp(si.argv[2], "core=", 5) == 0) {
159 char *p = strchr(si.argv[2], '=');
161 coreid = strtol(p + 1, NULL, 10);
169 // discard 'dist-serv' and 'core=x' argument
170 for (int i = 1; i <= si.argc - extra_args; i++) {
171 si.argv[i] = si.argv[i+extra_args];
175 debug_printf("starting dist-serv %s on core %d\n", si.name, coreid);
177 domainid_t new_domain;
178 err = spawn_program(coreid, si.name, si.argv, environ,
180 if (err_is_fail(err)) {
181 DEBUG_ERR(err, "spawn of %s failed", si.name);
185 char c = si.shortname[si.shortnamelen];
186 si.shortname[si.shortnamelen] = '\0';
188 // wait until fully started
189 err = nsb_wait_ready(si.shortname);
190 if (err_is_fail(err)) {
191 DEBUG_ERR(err, "nsb_wait_ready on %s failed", si.shortname);
194 si.shortname[si.shortnamelen] = c;
196 // HACK: make sure we use the local versions of a service if
197 // it was started. Really there needs to be a mechanism for that
198 // service to signal us and others to do this once it has started
200 set_local_bindings();
208 void spawn_arrakis_domains(void)
210 struct spawn_info si;
215 coreid_t my_coreid = disp_get_core_id();
219 r = prepare_spawn(&bmpos, &si);
222 } else if (r == -1) {
223 DEBUG_ERR(STARTD_ERR_BOOTMODULES,
224 "failed to read bootmodules entry");
227 /* Only spawn special arrakis modules */
228 if (si.argc >= 2 && strcmp(si.argv[1], "arrakis") == 0) {
234 if (si.argc >= 3 && strncmp(si.argv[2], "core=", 5) == 0) {
236 char *p = strchr(si.argv[2], '=');
238 coreid = strtol(p + 1, NULL, 10);
246 // discard 'dist-serv' and 'core=x' argument
247 for (int i = 1; i <= si.argc - extra_args; i++) {
248 si.argv[i] = si.argv[i+extra_args];
252 debug_printf("starting arrakis domain %s on core %d\n", si.name, coreid);
254 domainid_t new_domain;
255 err = spawn_arrakis_program(coreid, si.name, si.argv, environ,
256 NULL_CAP, NULL_CAP, 0, &new_domain);
257 if (err_is_fail(err)) {
258 DEBUG_ERR(err, "spawn of %s failed", si.name);
268 void spawn_app_domains(void)
270 struct spawn_info si;
275 coreid_t my_coreid = disp_get_core_id();
279 bool spawn_here = true;
281 r = prepare_spawn(&bmpos, &si);
284 } else if (r == -1) {
285 DEBUG_ERR(STARTD_ERR_BOOTMODULES,
286 "failed to read bootmodules entry");
289 /* Do not spawn special domains */
290 if (strncmp(si.shortname, "init", si.shortnamelen) == 0
291 || strncmp(si.shortname, "cpu", si.shortnamelen) == 0
292 // Adding following condition for cases like "cpu_omap44xx"
293 || strncmp(si.shortname, "cpu", strlen("cpu")) == 0
294 || strncmp(si.shortname, "boot_", strlen("boot_")) == 0
295 || strncmp(si.shortname, "monitor", si.shortnamelen) == 0
296 || strncmp(si.shortname, "mem_serv", si.shortnamelen) == 0
298 || strncmp(si.shortname, "corectrl", si.shortnamelen) == 0
304 /* Do not spawn special boot modules, dist-serv modules
305 or nospawn modules */
306 if (si.argc >= 2 && (strcmp(si.argv[1], "boot") == 0
307 || strcmp(si.argv[1], "dist-serv") == 0
308 || strcmp(si.argv[1], "nospawn") == 0
309 || strcmp(si.argv[1], "arrakis") == 0
310 || strcmp(si.argv[1], "auto") == 0)) {
318 uint8_t spawn_flags = 0;
319 uint8_t has_spawn_flags = 0;
320 uint8_t has_core = 0;
321 char *core_ptr = NULL;
323 for(int i = 1; i < si.argc && i < 3; ++i) {
324 if(strncmp(si.argv[i], "spawnflags=", 11) == 0) {
325 char *p = strchr(si.argv[i], '=') + 1;
326 spawn_flags = (uint8_t)strtol(p, (char **)&p, 10);
328 } else if (strncmp(si.argv[i], "core=", 5)== 0) {
329 core_ptr = strchr(si.argv[i], '=') + 1;
336 if (has_core || has_spawn_flags) {
337 for (int i = 1; i < si.argc; i++) {
338 if (has_spawn_flags && has_core) {
339 si.argv[i] = si.argv[i+2];
341 si.argv[i] = si.argv[i+1];
346 si.argc -= (has_core + has_spawn_flags);
349 while(*core_ptr != '\0') {
350 int id_from = strtol(core_ptr, (char **)&core_ptr, 10);
352 if(*core_ptr == '-') {
354 id_to = strtol(core_ptr, (char **)&core_ptr, 10);
356 assert(*core_ptr == ',' || *core_ptr == '\0');
357 if(*core_ptr != '\0') {
361 /* coreid = strtol(p + 1, NULL, 10); */
362 // discard 'core=x' argument
363 for(int i = id_from; i <= id_to; i++) {
364 debug_printf("starting app %s on core %d\n",
367 struct capref ret_domain_cap;
368 err = proc_mgmt_spawn_program(i, si.name,
369 si.argv, environ, spawn_flags,
371 if (err_is_fail(err)) {
372 DEBUG_ERR(err, "spawn of %s failed", si.name);
380 debug_printf("starting app %s on core %d\n", si.name, coreid);
382 struct capref ret_domain_cap;
383 err = proc_mgmt_spawn_program(coreid, si.name,
384 si.argv, environ, spawn_flags,
386 if (err_is_fail(err)) {
387 DEBUG_ERR(err, "spawn of %s failed", si.name);
398 void spawn_bootscript_domains(void)
401 coreid_t my_coreid = disp_get_core_id();
402 char *argv[256], *name;
404 // open bootmodules file and read it in
405 FILE *f = fopen("/bootscript", "r");
407 printf("No bootscript\n");
411 while(fgets(line, 1024, f) != NULL) {
414 // ignore comments (#) and empty lines
415 if (line[0] == '#' || line[0] == '\n') {
419 argv[0] = strtok(line, " \n");
421 for(argc = 1;; argc++) {
422 argv[argc] = strtok(NULL, " \n");
423 if(argv[argc] == NULL) {
429 if (argc >= 2 && strncmp(argv[1], "core=", 5) == 0) {
430 char *p = strchr(argv[1], '=');
435 int id_from = strtol(p, (char **)&p, 10), id_to = id_from;
438 id_to = strtol(p, (char **)&p, 10);
440 assert(*p == ',' || *p == '\0');
445 /* coreid = strtol(p + 1, NULL, 10); */
446 // discard 'core=x' argument
447 for (int i = 1; i < argc; i++) {
452 for(int i = id_from; i <= id_to; i++) {
453 debug_printf("starting app %s on core %d\n", name, i);
455 domainid_t new_domain;
456 err = spawn_program(i, name, argv, environ,
458 if (err_is_fail(err)) {
459 DEBUG_ERR(err, "spawn of %s failed", name);
464 debug_printf("starting app %s on core %d\n", name, my_coreid);
466 domainid_t new_domain;
467 err = spawn_program(my_coreid, name, argv, environ,
469 if (err_is_fail(err)) {
470 DEBUG_ERR(err, "spawn of %s failed", name);