spawn: added handling of spawn flags
authorReto Achermann <acreto@student.ethz.ch>
Thu, 28 Aug 2014 08:06:50 +0000 (10:06 +0200)
committerReto Achermann <acreto@student.ethz.ch>
Thu, 28 Aug 2014 08:06:50 +0000 (10:06 +0200)
Added a spawnflags parameter to the command line and forwarding of
spawnflags to spawnd

Added a spawn flag SPAWN_FLAGS_OMP for parsing openMP functions.

14 files changed:
if/spawn.if
include/barrelfish/spawn_client.h
include/elf/elf.h
include/spawndomain/spawndomain.h
lib/barrelfish/spawn_client.c
lib/elf/elf32.c
lib/elf/elf64.c
lib/spawndomain/Hakefile
lib/spawndomain/arch/x86/spawn_arch.c
lib/spawndomain/spawn.c
lib/spawndomain/spawn.h
lib/spawndomain/spawn_omp.c [new file with mode: 0644]
usr/spawnd/service.c
usr/startd/spawn.c

index 0990dac..81cedc4 100644 (file)
@@ -13,11 +13,11 @@ interface spawn "Interface to spawn domains" {
     } ps_entry;
 
     rpc spawn_domain(in string path, in char argvbuf[argvbytes], in char envbuf[envbytes],
-                     out errval err, out domainid domain_id);
+                     in uint8 flags, out errval err, out domainid domain_id);
 
     rpc spawn_domain_with_caps(in string path, in char argvbuf[argvbytes],
                                in char envbuf[envbytes], in cap inheritcn_cap,
-                               in cap argcn_cap, out errval err,
+                               in cap argcn_cap, in uint8 flags, out errval err,
                                out domainid domain_id);
 
     rpc use_local_memserv();
index 5fc7671..c7b7eb1 100644 (file)
@@ -18,6 +18,7 @@ __BEGIN_DECLS
 /// Flags for spawning a program
 typedef enum spawn_flags {
     SPAWN_NEW_DOMAIN    = 1 << 0, ///< allocate a new domain ID
+    SPAWN_OMP           = 1 << 1, ///< do the OpenMP parsing
 } spawn_flags_t;
 
 struct spawn_ps_entry {
index 87670d4..2f6f0f4 100644 (file)
@@ -743,10 +743,12 @@ elf32_find_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
                           uintptr_t *index);
 uint32_t
 elf64_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
-                          const char *name, uint8_t contains, uint8_t type);
+                          const char *name, uint8_t contains, uint8_t type,
+                          size_t *ret_bytes);
 uint32_t
 elf32_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
-                          const char *name, uint8_t contains, uint8_t type);
+                          const char *name, uint8_t contains, uint8_t type,
+                          size_t *ret_bytes);
 struct Elf64_Sym *
 elf64_find_symbol_by_addr(genvaddr_t elf_base, size_t elf_bytes,
                           lvaddr_t addr, uintptr_t *index);
index a418eef..28e77b6 100644 (file)
@@ -62,8 +62,17 @@ struct spawninfo {
     size_t eh_frame_size;
     genvaddr_t eh_frame_hdr;
     size_t eh_frame_hdr_size;
+
+    // name of the image
+    const char *name;
+    
+    // spawn flags
+    uint8_t flags;
 };
 
+#define SPAWN_FLAGS_NEW_DOMAIN    (1 << 0) ///< allocate a new domain ID
+#define SPAWN_FLAGS_OMP           (1 << 1) ///< do the OpenMP parsing
+
 __BEGIN_DECLS
 errval_t spawn_get_cmdline_args(struct mem_region *module,
                                 char **retargs);
index de6875e..6ef5f6d 100644 (file)
@@ -255,12 +255,12 @@ errval_t spawn_program_with_caps(coreid_t coreid, const char *path,
 
     if (capref_is_null(inheritcn_cap) && capref_is_null(argcn_cap)) {
         err = cl->vtbl.spawn_domain(cl, path, argstr, argstrlen,
-                                    envstr, envstrlen,
+                                    envstr, envstrlen, flags,
                                     &msgerr, &domain_id);
     } else {
         err = cl->vtbl.spawn_domain_with_caps(cl, path, argstr, argstrlen,
                                               envstr, envstrlen, inheritcn_cap,
-                                              argcn_cap, &msgerr, &domain_id);
+                                              argcn_cap, flags, &msgerr, &domain_id);
     }
     if (err_is_fail(err)) {
         USER_PANIC_ERR(err, "error sending spawn request");
index 11e930e..f3a1541 100644 (file)
@@ -231,7 +231,8 @@ elf32_find_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
 
 uint32_t
 elf32_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
-                          const char *name, uint8_t contains, uint8_t type)
+                          const char *name, uint8_t contains, uint8_t type,
+                          size_t *ret_bytes)
 {
     struct Elf32_Sym *sym = NULL;
     struct Elf32_Shdr *shead;
@@ -247,6 +248,7 @@ elf32_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
     }
 
     uint32_t count = 0;
+    size_t bytes = 0;
 
     shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);
 
@@ -273,14 +275,20 @@ elf32_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
             if (strcmp(symname, name)==0) {
                 /* we have a match */
                 count++;
+                bytes += strlen(symname)+1;
             }
         } else {
             if (strstr(symname,name) != 0) {
                 count++;
+                bytes += strlen(symname)+1;
             }
         }
     }
 
+    if (ret_bytes) {
+        *ret_bytes = bytes;
+    }
+
     return count;
 }
 
index eecf971..bcfc395 100644 (file)
@@ -213,7 +213,8 @@ elf64_find_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
 
 uint32_t
 elf64_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
-                           const char *name, uint8_t contains, uint8_t type)
+                           const char *name, uint8_t contains, uint8_t type,
+                           size_t *ret_bytes)
 {
     struct Elf64_Sym *sym = NULL;
     struct Elf64_Shdr *shead;
@@ -221,6 +222,7 @@ elf64_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
     const char *symname = NULL;
 
     uint32_t count = 0;
+    size_t bytes = 0;
 
     lvaddr_t elfbase = (lvaddr_t)elf_base;
     struct Elf64_Ehdr *head = (struct Elf64_Ehdr *)elfbase;
@@ -255,14 +257,20 @@ elf64_count_symbol_by_name(genvaddr_t elf_base, size_t elf_bytes,
             if (strcmp(symname, name)==0) {
                 /* we have a match */
                 count++;
+                bytes += strlen(symname)+1;
             }
         } else {
             if (strstr(symname,name) != NULL) {
                 count++;
+                bytes += strlen(symname)+1;
             }
         }
     }
 
+    if (ret_bytes) {
+        *ret_bytes = bytes;
+    }
+
     return count;
 }
 
index 24ea7c8..39d8965 100644 (file)
@@ -11,7 +11,8 @@
 --------------------------------------------------------------------------
 
 [(let
-     common_srcs = [ "spawn_vspace.c", "spawn.c", "getopt.c", "multiboot.c" ]
+     common_srcs = [ "spawn_vspace.c", "spawn.c", "getopt.c", "multiboot.c",
+                     "spawn_omp.c" ]
 
      arch_srcs "x86_32"  = [ "arch/x86/spawn_arch.c" ]
      arch_srcs "x86_64"  = [ "arch/x86/spawn_arch.c" ]
@@ -24,8 +25,8 @@
                     cFiles = common_srcs ++ arch_srcs (archFamily arch),
                     addIncludes = [ "/lib/barrelfish/include/arch" 
                                     ./. archFamily arch ],
-                    flounderDefs = [ "monitor" ],
+                    flounderDefs = [ "monitor", "octopus" ],
                     architectures = [ arch ],
-                    addLibraries = [ "trace" ]
+                    addLibraries = [ "trace", "octopus" ]
                 }
  )  | arch <- allArchitectures ]
index 5414455..7bbf699 100644 (file)
@@ -175,6 +175,72 @@ static errval_t elf_allocate(void *state, genvaddr_t base, size_t size,
     return SYS_ERR_OK;
 }
 
+static errval_t spawn_parse_omp_functions(const char *name,
+                                          lvaddr_t binary, size_t binary_size)
+{
+    errval_t err;
+    genvaddr_t value;
+    err = spawn_symval_lookup(name, 0, NULL, &value);
+    if (err_is_ok(err)) {
+        return SYS_ERR_OK;
+    }
+
+    uint32_t count = 0;
+
+    struct Elf64_Sym *sym = NULL;
+    struct Elf64_Shdr *shead;
+    struct Elf64_Shdr *symtab;
+    const char *symname = NULL;
+
+    lvaddr_t elfbase = (lvaddr_t)binary;
+    struct Elf64_Ehdr *head = (struct Elf64_Ehdr *)elfbase;
+
+    // just a sanity check
+    if (!IS_ELF(*head) || head->e_ident[EI_CLASS] != ELFCLASS64) {
+        return ELF_ERR_HEADER;
+    }
+
+    shead = (struct Elf64_Shdr *)(elfbase + (uintptr_t)head->e_shoff);
+
+    symtab = elf64_find_section_header_type(shead, head->e_shnum, SHT_SYMTAB);
+
+    uintptr_t symbase = elfbase + (uintptr_t)symtab->sh_offset;
+
+    uint32_t index = 1;
+    for (uintptr_t i = 0; i < symtab->sh_size; i += sizeof(struct Elf64_Sym)) {
+        // getting the symbol
+        sym = (struct Elf64_Sym *)(symbase + i);
+
+        // check for matching type
+        if ((sym->st_info & 0x0F) != STT_FUNC) {
+            continue;
+        }
+
+        // find the section of the associated string table
+        struct Elf64_Shdr *strtab = shead+symtab->sh_link;
+
+        // get the pointer to the symbol name from string table + string index
+        symname = (const char *)elfbase + strtab->sh_offset + sym->st_name;
+
+        if (strstr(symname, "_omp_fn") != NULL) {
+            count++;
+            err = spawn_symval_register(name, index++,  symname, sym->st_value);
+            if (err_is_fail(err)) {
+                DEBUG_ERR(err, "could not register symbol. %s\n", symname);
+                return err;
+            }
+        }
+    }
+
+    err = spawn_symval_register(name, 0, "binary", count);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "could not register symbol: %s.binary", name);
+        return err;
+    }
+
+    return SYS_ERR_OK;
+}
+
 /**
  * \brief Load the elf image
  */
@@ -214,6 +280,11 @@ errval_t spawn_arch_load(struct spawninfo *si,
         return err;
     }
 
+    if (si->flags & SPAWN_FLAGS_OMP) {
+        debug_printf("parsing OMP symbols\n");
+        return spawn_parse_omp_functions(si->name, binary, binary_size);
+    }
+
     return SYS_ERR_OK;
 }
 
index f0984e3..d4d0dc1 100644 (file)
@@ -710,6 +710,7 @@ errval_t spawn_load_image(struct spawninfo *si, lvaddr_t binary,
         return err_push(err, SPAWN_ERR_VSPACE_INIT);
     }
 
+    si->name = name;
     genvaddr_t entry;
     void* arch_info;
     /* Load the image */
@@ -817,7 +818,7 @@ errval_t spawn_load_with_args(struct spawninfo *si, struct mem_region *module,
     /* Load the image */
     genvaddr_t entry;
     void* arch_info;
-
+    si->name = name;
     err = spawn_arch_load(si, binary, binary_size, &entry, &arch_info);
     if (err_is_fail(err)) {
         return err_push(err, SPAWN_ERR_LOAD);
@@ -883,6 +884,7 @@ errval_t spawn_load_with_bootinfo(struct spawninfo *si, struct bootinfo *bi,
     /* Load the image */
     genvaddr_t entry;
     void* arch_info;
+    si->name = name;
     err = spawn_arch_load(si, binary, binary_size, &entry, &arch_info);
     if (err_is_fail(err)) {
         return err_push(err, SPAWN_ERR_LOAD);
index e896e0a..cd0199c 100644 (file)
@@ -19,4 +19,8 @@ lvaddr_t map_module(struct mem_region *module, size_t *retsize);
 const char *getopt(const char **optstring, char *buf, size_t buflen,
                    size_t *optlen);
 
+errval_t spawn_symval_register(const char *binary, uint32_t idx,
+                               const char *symname, genvaddr_t addres);
+errval_t spawn_symval_lookup(const char *binary, uint32_t idx,
+                             char **ret_name, genvaddr_t *ret_add);
 #endif
diff --git a/lib/spawndomain/spawn_omp.c b/lib/spawndomain/spawn_omp.c
new file mode 100644 (file)
index 0000000..5935dfe
--- /dev/null
@@ -0,0 +1,137 @@
+/**
+ * \file
+ * \brief functionality to spawn domains
+ */
+
+/*
+ * Copyright (c) 2014 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/nameservice_client.h>
+
+#include <if/octopus_defs.h>
+#include <if/octopus_rpcclient_defs.h>
+#include <if/monitor_defs.h>
+#include <octopus/getset.h> // for oct_read TODO
+#include <octopus/trigger.h> // for NOP_TRIGGER
+
+
+#include "spawn.h"
+
+errval_t spawn_symval_lookup(const char *binary, uint32_t idx,
+                             char **ret_name, genvaddr_t *ret_addr)
+{
+    errval_t err;
+
+    size_t len;
+
+    if (binary[0]== '_') {
+        binary++;
+    }
+
+    len = snprintf(NULL, 0, "%s.omp.%u", binary, idx);
+    char *omp_entry = malloc(len+1);
+    if (omp_entry == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+    snprintf(omp_entry, len+1, "%s.omp.%u", binary, idx);
+
+    struct octopus_rpc_client *r = get_octopus_rpc_client();
+    if (r == NULL) {
+        return LIB_ERR_NAMESERVICE_NOT_BOUND;
+    }
+
+    // transform to lower case
+    for (int i = 0; i < len; ++i) {
+        if (omp_entry[i] >= 'A' && omp_entry[i] <= 'Z') {
+            omp_entry[i] -= ('A'-'a');
+        }
+    }
+
+    char* record = NULL;
+    octopus_trigger_id_t tid;
+    errval_t error_code;
+    err = r->vtbl.get(r, omp_entry, NOP_TRIGGER, &record, &tid, &error_code);
+    if (err_is_fail(err)) {
+        goto out;
+    }
+    err = error_code;
+    if (err_is_fail(err)) {
+        if (err_no(err) == OCT_ERR_NO_RECORD) {
+            err = err_push(err, LIB_ERR_NAMESERVICE_UNKNOWN_NAME);
+        }
+        goto out;
+    }
+
+    uint64_t addr = 0;
+    char *symname = NULL;
+    err = oct_read(record, "_ { sym: %s, addr: %d }", &symname, &addr);
+    if (err_is_fail(err) || symname == NULL) {
+        err = err_push(err, LIB_ERR_NAMESERVICE_INVALID_NAME);
+        goto out;
+    }
+    if (ret_addr != NULL) {
+        *ret_addr = addr;
+    }
+    if (ret_name != NULL) {
+        *ret_name = strdup(symname);
+    }
+
+out:
+    free(record);
+    free(omp_entry);
+    return err;
+}
+
+errval_t spawn_symval_register(const char *binary, uint32_t idx,
+                               const char *symname, genvaddr_t address)
+{
+
+    errval_t err = SYS_ERR_OK;
+
+    struct octopus_rpc_client *r = get_octopus_rpc_client();
+    if (r == NULL) {
+        return LIB_ERR_NAMESERVICE_NOT_BOUND;
+    }
+
+    if (symname[0] == '_') {
+        symname++;
+    }
+    // Format record
+    static const char* format = "%s.omp.%u { sym: %s, addr: %d }";
+    size_t len = snprintf(NULL, 0, format, binary, idx, symname, address);
+    char* record = malloc(len+1);
+    if (record == NULL) {
+        return LIB_ERR_MALLOC_FAIL;
+    }
+    snprintf(record, len+1, format, binary, idx, symname, address);
+    // transform to lower case
+    for (int i = 0; i < len; ++i) {
+        if (record[i] >= 'A' && record[i] <= 'Z') {
+            record[i] -= ('A'-'a');
+        }
+    }
+
+    char* ret = NULL;
+    octopus_trigger_id_t tid;
+    errval_t error_code;
+    err = r->vtbl.set(r, record, 0, NOP_TRIGGER, 0, &ret, &tid, &error_code);
+    if (err_is_fail(err)) {
+        goto out;
+    }
+    err = error_code;
+
+out:
+    free(record);
+    return err;
+}
+
index df4a61f..e1b7a3b 100644 (file)
@@ -32,7 +32,7 @@
 static errval_t spawn(char *path, char *const argv[], char *argbuf,
                       size_t argbytes, char *const envp[],
                       struct capref inheritcn_cap, struct capref argcn_cap,
-                      domainid_t *domainid)
+                      uint8_t flags, domainid_t *domainid)
 {
     errval_t err, msgerr;
 
@@ -88,6 +88,7 @@ static errval_t spawn(char *path, char *const argv[], char *argbuf,
 
     /* spawn the image */
     struct spawninfo si;
+    si.flags = flags;
     err = spawn_load_image(&si, (lvaddr_t)image, info.size, CURRENT_CPU_TYPE,
                            name, my_core_id, argv, envp, inheritcn_cap,
                            argcn_cap);
@@ -294,7 +295,8 @@ static void spawn_with_caps_handler(struct spawn_binding *b, char *path,
                                     char *argbuf, size_t argbytes,
                                     char *envbuf, size_t envbytes,
                                     struct capref inheritcn_cap,
-                                    struct capref argcn_cap)
+                                    struct capref argcn_cap,
+                                    uint8_t flags)
 {
     errval_t err;
     domainid_t domainid = 0;
@@ -334,7 +336,7 @@ static void spawn_with_caps_handler(struct spawn_binding *b, char *path,
     vfs_path_normalise(path);
 
     err = spawn(path, argv, argbuf, argbytes, envp, inheritcn_cap, argcn_cap,
-                &domainid);
+                flags, &domainid);
     if (!capref_is_null(inheritcn_cap)) {
         errval_t err2;
         err2 = cap_delete(inheritcn_cap);
@@ -365,10 +367,11 @@ static void spawn_with_caps_handler(struct spawn_binding *b, char *path,
 
 
 static void spawn_handler(struct spawn_binding *b, char *path, char *argbuf,
-                          size_t argbytes, char *envbuf, size_t envbytes)
+                          size_t argbytes, char *envbuf, size_t envbytes,
+                          uint8_t flags)
 {
     spawn_with_caps_handler(b, path, argbuf, argbytes, envbuf, envbytes,
-                            NULL_CAP, NULL_CAP);
+                            NULL_CAP, NULL_CAP, flags);
 }
 
 /**
index bb88e82..3ed8fc4 100644 (file)
@@ -310,6 +310,22 @@ void spawn_app_domains(void)
 
             coreid_t coreid;
 
+            uint8_t spawn_flags = 0;
+            uint8_t has_spawn_flags = 1;
+            if (si.argc >= 2) {
+                char *p = NULL;
+                if (strncmp(si.argv[1], "spawnflags=", 11) == 0) {
+                    p = strchr(si.argv[1], '=');
+                } else if (strncmp(si.argv[2], "spawnflags=", 11) == 0) {
+                    p = strchr(si.argv[2], '=');
+                }
+                if (p != NULL) {
+                    p++;
+                    spawn_flags = (uint8_t)strtol(p, (char **)&p, 10);
+                    has_spawn_flags = 1;
+                }
+            }
+
             // get core id
             if (si.argc >= 2 && strncmp(si.argv[1], "core=", 5) == 0) {
 
@@ -331,9 +347,17 @@ void spawn_app_domains(void)
                     /* coreid = strtol(p + 1, NULL, 10); */
                     // discard 'core=x' argument
                     for (int i = 1; i < si.argc; i++) {
-                        si.argv[i] = si.argv[i+1];
+                        if (has_spawn_flags) {
+                            si.argv[i] = si.argv[i+2];
+                        } else {
+                            si.argv[i] = si.argv[i+1];
+                        }
+                    }
+                    if (has_spawn_flags) {
+                        si.argc -= 2;
+                    } else {
+                        si.argc--;
                     }
-                    si.argc--;
 
                     for(int i = id_from; i <= id_to; i++) {
                         debug_printf("starting app %s on core %d\n",
@@ -341,7 +365,7 @@ void spawn_app_domains(void)
 
                         domainid_t new_domain;
                         err = spawn_program(i, si.name, si.argv, environ,
-                                            0, &new_domain);
+                                            spawn_flags, &new_domain);
                         if (err_is_fail(err)) {
                             DEBUG_ERR(err, "spawn of %s failed", si.name);
                         }
@@ -350,11 +374,18 @@ void spawn_app_domains(void)
             } else {
                 coreid = my_coreid;
 
+                if (has_spawn_flags) {
+                    for (int i = 1; i < si.argc; i++) {
+                        si.argv[i] = si.argv[i+1];
+                    }
+                    si.argc--;
+                }
+
                 debug_printf("starting app %s on core %d\n", si.name, coreid);
 
                 domainid_t new_domain;
                 err = spawn_program(coreid, si.name, si.argv, environ,
-                                    0, &new_domain);
+                                    spawn_flags, &new_domain);
                 if (err_is_fail(err)) {
                     DEBUG_ERR(err, "spawn of %s failed", si.name);
                 }