} 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();
/// 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 {
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);
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);
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");
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;
}
uint32_t count = 0;
+ size_t bytes = 0;
shead = (struct Elf32_Shdr *)(elfbase + (uintptr_t)head->e_shoff);
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;
}
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;
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;
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;
}
--------------------------------------------------------------------------
[(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" ]
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 ]
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
*/
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;
}
return err_push(err, SPAWN_ERR_VSPACE_INIT);
}
+ si->name = name;
genvaddr_t entry;
void* arch_info;
/* Load the image */
/* 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);
/* 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);
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
--- /dev/null
+/**
+ * \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;
+}
+
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;
/* 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);
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;
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);
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);
}
/**
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) {
/* 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",
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);
}
} 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);
}