proc_mgmt: merged proc management client with spawnd client
authorRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 6 Oct 2017 13:49:15 +0000 (15:49 +0200)
committerRoni Häcki <roni.haecki@inf.ethz.ch>
Fri, 6 Oct 2017 13:49:15 +0000 (15:49 +0200)
Signed-off-by: Roni Häcki <roni.haecki@inf.ethz.ch>

13 files changed:
include/barrelfish/proc_mgmt_client.h [deleted file]
include/barrelfish/spawn_client.h
lib/barrelfish/Hakefile
lib/barrelfish/init.c
lib/barrelfish/proc_mgmt_client.c [deleted file]
lib/barrelfish/spawn_client.c
usr/examples/xmpl-spawn/spawn.c
usr/monitor/inter.c
usr/monitor/main.c
usr/monitor/monitor_server.c
usr/proc_mgmt/service.c
usr/startd/spawn.c
usr/tests/proc_mgmt_test/main.c

diff --git a/include/barrelfish/proc_mgmt_client.h b/include/barrelfish/proc_mgmt_client.h
deleted file mode 100644 (file)
index ffafa30..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * \file
- * \brief Client for interacting with the process management server.
- */
-
-/*
- * Copyright (c) 2017, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef BARRELFISH_PROC_MGMT_CLIENT_H
-#define BARRELFISH_PROC_MGMT_CLIENT_H
-
-#include <sys/cdefs.h>
-
-__BEGIN_DECLS
-
-struct proc_mgmt_lmp_binding;
-
-
-/* XXX: duplicate of proc_mgmt_bind_continuation_fn in generated code */
-typedef void proc_mgmt_bind_continuation_fn(void *st, errval_t err,
-                                            struct proc_mgmt_binding *_binding);
-
-errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
-                                     struct waitset *ws,
-                                     size_t lmp_buflen_words);
-errval_t proc_mgmt_client_lmp_bind(struct proc_mgmt_lmp_binding *lmpb,
-                                   struct capref ep,
-                                   proc_mgmt_bind_continuation_fn *cont,
-                                   void *st,
-                                   struct waitset *ws,
-                                   size_t lmp_buflen_words);
-errval_t proc_mgmt_bind_client(void);
-
-errval_t proc_mgmt_add_spawnd(iref_t iref, coreid_t core_id);
-errval_t proc_mgmt_spawn_program(coreid_t core_id, const char *path,
-                                    char *const argv[], char *const envp[],
-                                 uint8_t flags, struct capref *ret_domain_cap);
-errval_t proc_mgmt_spawn_program_with_caps(coreid_t core_id, const char *path,
-                                 char *const argv[], char *const envp[],
-                                 struct capref inheritcn_cap,
-                                 struct capref argcn_cap, uint8_t flags,
-                                 struct capref *ret_domain_cap);
-errval_t proc_mgmt_span(coreid_t core_id);
-errval_t proc_mgmt_kill(struct capref domain_cap);
-errval_t proc_mgmt_exit(uint8_t status);
-errval_t proc_mgmt_wait(struct capref domain_cap, uint8_t *status);
-
-__END_DECLS
-
-#endif // BARRELFISH_PROC_MGMT_CLIENT_H
index 073b9dc..e6ab4c9 100644 (file)
@@ -26,6 +26,25 @@ struct spawn_ps_entry {
 #define INHERITCN_SLOT_SESSIONID 2  ///< Session ID domain belongs to
 #define INHERITCN_SLOT_KERNELCAP 3     ///< Kernel capability for core boot
 
+struct proc_mgmt_lmp_binding;
+
+
+/* XXX: duplicate of proc_mgmt_bind_continuation_fn in generated code */
+typedef void proc_mgmt_bind_continuation_fn(void *st, errval_t err,
+                                            struct proc_mgmt_binding *_binding);
+
+errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
+                                     struct waitset *ws,
+                                     size_t lmp_buflen_words);
+errval_t proc_mgmt_client_lmp_bind(struct proc_mgmt_lmp_binding *lmpb,
+                                   struct capref ep,
+                                   proc_mgmt_bind_continuation_fn *cont,
+                                   void *st,
+                                   struct waitset *ws,
+                                   size_t lmp_buflen_words);
+errval_t proc_mgmt_bind_client(void);
+
+errval_t proc_mgmt_add_spawnd(iref_t iref, coreid_t core_id);
 errval_t spawn_program_with_caps(coreid_t coreid, const char *path,
                                  char *const argv[], char *const envp[],
                                  struct capref inheritcn_cap,
@@ -43,6 +62,7 @@ errval_t spawn_program_on_all_cores(bool same_core, const char *path,
                                     char *const argv[], char *const envp[],
                                     spawn_flags_t flags, struct capref *ret_domain_cap,
                                     coreid_t* spawn_count);
+errval_t spawn_span(coreid_t core_id);
 errval_t spawn_kill(struct capref domain_cap);
 errval_t spawn_exit(uint8_t exitcode);
 errval_t spawn_wait_coreid(coreid_t coreid, struct capref domain_cap, uint8_t *exitcode, bool nohang);
index aa66202..a503651 100644 (file)
@@ -16,7 +16,7 @@
 let common_srcs = [ "capabilities.c", "init.c", "dispatch.c", "threads.c",
                     "thread_once.c", "thread_sync.c", "slab.c", "domain.c", "idc.c",
                     "waitset.c", "event_queue.c", "event_mutex.c",
-                    "idc_export.c", "nameservice_client.c", "msgbuf.c", "proc_mgmt_client.c",
+                    "idc_export.c", "nameservice_client.c", "msgbuf.c",
                     "monitor_client.c", "flounder_support.c", "flounder_glue_binding.c",
                     "flounder_txqueue.c","morecore.c", "debug.c", "heap.c",
                     "ram_alloc.c", "terminal.c", "spawn_client.c", "vspace/vspace.c",
index a278227..69df1d7 100644 (file)
@@ -25,7 +25,6 @@
 #include <barrelfish/morecore.h>
 #include <barrelfish/monitor_client.h>
 #include <barrelfish/nameservice_client.h>
-#include <barrelfish/proc_mgmt_client.h>
 #include <barrelfish/spawn_client.h>
 #include <barrelfish/systime.h>
 #include <barrelfish_kpi/domain_params.h>
@@ -70,14 +69,9 @@ void libc_exit(int status)
 
         // XXX: Leak all other domain allocations
     } else {
-        err = proc_mgmt_exit(status);
+        err = spawn_exit(status);
         if (err_is_fail(err)) {
-            // Maybe we have not been spawned through the process manager, but
-            // through spawnd directly (we're some bootstrap domain).
-            err = spawn_exit(status);
-            if (err_is_fail(err)) {
-                DEBUG_ERR(err, "spawn_exit");
-            }
+            DEBUG_ERR(err, "spawn_exit");
         }
     }
 
diff --git a/lib/barrelfish/proc_mgmt_client.c b/lib/barrelfish/proc_mgmt_client.c
deleted file mode 100644 (file)
index b2600e7..0000000
+++ /dev/null
@@ -1,531 +0,0 @@
-/**
- * \file
- * \brief Client for interacting with the process management server.
- */
-
-/*
- * Copyright (c) 2017, 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, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#include <barrelfish/barrelfish.h>
-#include <barrelfish/nameservice_client.h>
-#include <barrelfish/proc_mgmt_client.h>
-#include <if/octopus_defs.h>
-#include <if/proc_mgmt_defs.h>
-#include <vfs/vfs_path.h>
-
-struct proc_mgmt_bind_retst {
-    errval_t err;
-    struct proc_mgmt_binding *b;
-    bool present;
-};
-
-extern char **environ;
-
-static void error_handler(struct proc_mgmt_binding *b, errval_t err)
-{
-#if defined(__x86_64__) || defined(__i386__)
-    debug_printf("%p \n",  __builtin_return_address(0));
-#endif
-    debug_err(__FILE__, __func__, __LINE__, err,
-              "asynchronous error in proc_mgmt binding");
-    abort();
-}
-
-static void proc_mgmt_bind_cont(void *st, errval_t err,
-        struct proc_mgmt_binding *b)
-{
-    struct proc_mgmt_bind_retst *retst = (struct proc_mgmt_bind_retst*) st;
-    assert(retst != NULL);
-    assert(!retst->present);
-    retst->err = err;
-    retst->b = b;
-    retst->present = true;
-    b->st = retst;
-}
-
-static void proc_mgmt_accept_recv_handler(void *arg)
-{
-    struct proc_mgmt_lmp_binding *b = arg;
-    struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
-    struct capref cap;
-    errval_t err;
-
-    // try to retrieve a message from the channel
-    err = lmp_chan_recv(&b->chan, &msg, &cap);
-    if (err_is_fail(err)) {
-        if (err_no(err) == LIB_ERR_NO_LMP_MSG) {
-            // nothing there, re-register
-            struct event_closure recv_handler = {
-                .handler = proc_mgmt_accept_recv_handler,
-                .arg = b,
-            };
-            err = lmp_chan_register_recv(&b->chan, b->b.waitset, recv_handler);
-            b->b.error_handler(&b->b, err_push(err, LIB_ERR_CHAN_REGISTER_RECV));
-        } else {
-            // real error, report to user
-            b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_CHAN_RECV));
-        }
-        return;
-    }
-
-    // TODO(razvan): LMP_PROC_MGMT_ACCEPT ?
-    assert(b->chan.connstate == LMP_MONITOR_ACCEPT);
-    assert(!capref_is_null(cap));
-    b->chan.remote_cap = cap;
-    b->chan.connstate = LMP_CONNECTED;
-
-    /* allocate a new receive slot */
-    err = lmp_chan_alloc_recv_slot(&b->chan);
-    if (err_is_fail(err)) {
-        // XXX: report the error, but continue
-        b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_ALLOC_RECV_SLOT));
-    }
-
-    /* Run the RX handler; has a side-effect of registering for receive events */
-    proc_mgmt_lmp_rx_handler(b);
-}
-
-static errval_t init_lmp_binding(struct proc_mgmt_lmp_binding *lmpb,
-                                 struct waitset *ws,
-                                 size_t buflen_words)
-{
-    errval_t err;
-
-    proc_mgmt_lmp_init(lmpb, ws);
-
-    /* allocate a cap slot for the new endpoint cap */
-    err = slot_alloc(&lmpb->chan.local_cap);
-    if (err_is_fail(err)) {
-        return err_push(err, LIB_ERR_SLOT_ALLOC);
-    }
-
-    /* allocate a local endpoint */
-    err = lmp_endpoint_create_in_slot(buflen_words, lmpb->chan.local_cap,
-                                      &lmpb->chan.endpoint);
-    if (err_is_fail(err)) {
-        // TODO(razvan): Free cap slot.
-        return err_push(err, LIB_ERR_ENDPOINT_CREATE);
-    }
-
-    /* allocate an initial receive slot */
-    err = lmp_chan_alloc_recv_slot(&lmpb->chan);
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    /* setup error handler */
-    lmpb->b.error_handler = error_handler;
-
-    /* setup initial receive handlers */
-    // TODO(razvan): Don't think this is needed, but dunno for sure yet.
-    // lmpb->b.rx_vtbl = monitor_rx_vtbl;
-
-    // connect handlers
-    lmpb->b.change_waitset(&lmpb->b, lmpb->b.waitset);
-    return SYS_ERR_OK;
-}
-
-/**
- * \brief Accept a new LMP binding to a proc mgmt client.
- *
- * Should only be used in the process manager.
- *
- * \param lmpb         Storage for binding state
- * \param ws           Waitset for handling incoming messages
- * \param buflen_words Size of incoming buffer, in number of words
- */
-errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
-                                     struct waitset *ws,
-                                     size_t lmp_buflen_words)
-{
-    errval_t err = init_lmp_binding(lmpb, ws, lmp_buflen_words);
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    lmpb->chan.connstate = LMP_MONITOR_ACCEPT;  // TODO(razvan): LMP_PROC_MGMT_ACCEPT?
-    lmpb->chan.remote_cap = NULL_CAP; // will be sent to us by the client
-
-    /* Register for receive notification on our special handler */
-    struct event_closure receive_handler = {
-        .handler = proc_mgmt_accept_recv_handler,
-        .arg = lmpb,
-    };
-    err = lmp_chan_register_recv(&lmpb->chan, ws, receive_handler);
-    if (err_is_fail(err)) {
-        return err;  // TODO(razvan): cleanup?
-    }
-
-    return SYS_ERR_OK;
-}
-
-
-/**
- * \brief Initiate a new LMP binding to the process manager
- *
- * To be used by the monitor for setting up the privileged channel used for
- * spawnd discovery.
- * Requires an explicit remote endpoint cap allocated by the process manager.
- *
- * \param lmpb         Storage for binding state
- * \param ep           Remote endpoint of the process manager
- * \param ws           Waitset for handling incoming messages
- * \param cont         Continuation for when binding completes or fails
- * \param st           State passed to continuation function
- * \param buflen_words Size of incoming buffer, in number of words
- */
-errval_t proc_mgmt_client_lmp_bind(struct proc_mgmt_lmp_binding *lmpb,
-                                   struct capref ep,
-                                   proc_mgmt_bind_continuation_fn *cont,
-                                   void *st,
-                                   struct waitset *ws,
-                                   size_t lmp_buflen_words)
-{
-    errval_t err = init_lmp_binding(lmpb, ws, lmp_buflen_words);
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    lmpb->chan.remote_cap = ep;
-
-    // Send the local endpoint cap to the process manager.
-    lmpb->chan.connstate = LMP_CONNECTED; /* pre-established */
-    err = lmp_chan_send0(&lmpb->chan, 0, lmpb->chan.local_cap);
-    if (err_is_fail(err)) {
-        // TODO(razvan): This, below.
-        /* XXX: I'm lazily assuming this can never fail with a transient error,
-         * since we only do it once at dispatcher startup. If not, we need to
-         * register and retry here */
-        assert(!lmp_err_is_transient(err));
-        return err;
-    }
-
-    /* Run the RX handler; has a side-effect of registering for receive events */
-    proc_mgmt_lmp_rx_handler(lmpb);
-
-    /* Run the continuation */
-    cont(st, SYS_ERR_OK, &lmpb->b);
-
-    return SYS_ERR_OK;
-}
-
-errval_t proc_mgmt_bind_client(void)
-{
-    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
-    if (b != NULL) {
-        return SYS_ERR_OK;
-    }
-
-    errval_t err;
-    iref_t iref;
-    // Try using nameserver to retrievew the proc mgmt iref.
-    err = nameservice_blocking_lookup("proc_mgmt", &iref);
-    if (err_is_fail(err)) {
-        return err;
-    }
-    
-    // Initiate bind.
-    struct proc_mgmt_bind_retst bindst = {
-        .present = false
-    };
-
-    err = proc_mgmt_bind(iref, proc_mgmt_bind_cont, &bindst,
-            get_default_waitset(), /*IDC_BIND_FLAG_RPC_CAP_TRANSFER*/IDC_BIND_FLAGS_DEFAULT);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "proc_mgmt_bind");
-    }
-
-    // Wait for bind completion.
-    while (!bindst.present) {
-        messages_wait_and_handle_next();
-    }
-
-    if (err_is_fail(bindst.err)) {
-        return bindst.err;
-    }
-
-    proc_mgmt_rpc_client_init(bindst.b);
-
-    set_proc_mgmt_binding(bindst.b);
-
-    return SYS_ERR_OK;
-}
-
-errval_t proc_mgmt_add_spawnd(iref_t iref, coreid_t core_id)
-{
-    errval_t err = proc_mgmt_bind_client();
-    if (err_is_fail(err)) {
-        DEBUG_ERR(err, "proc_mgmt_bind_client");
-        return err;
-    }
-
-    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
-    assert(b != NULL);
-
-    err = b->tx_vtbl.add_spawnd(b, NOP_CONT, core_id, iref);
-    if (err_is_fail(err)) {
-        DEBUG_ERR(err, "add_spawnd");
-    }
-
-    return err;
-}
-
-/**
- * \brief Request the process manager to spawn a program on a specific core
- *
- * \param coreid          Core ID on which to spawn the program
- * \param path            Absolute path in the file system to an executable
- *                        image suitable for the given core
- * \param argv            Command-line arguments, NULL-terminated
- * \param envp            Optional environment, NULL-terminated
- *                        (pass NULL to inherit)
- * \param inheritcn_cap   Cap to a CNode containing capabilities to be inherited
- * \param argcn_cap       Cap to a CNode containing capabilities passed as
- *                        arguments
- * \param flags           Flags to spawn
- * \param ret_domain_cap  If non-NULL, filled in with domain cap of new domain
- *
- * \bug flags are currently ignored
- */
-errval_t proc_mgmt_spawn_program_with_caps(coreid_t core_id, const char *path,
-                                           char *const argv[],
-                                           char *const envp[],
-                                           struct capref inheritcn_cap,
-                                           struct capref argcn_cap,
-                                           uint8_t flags,
-                                           struct capref *ret_domain_cap)
-{
-    errval_t err, msgerr;
-
-    // default to copying our environment
-    if (envp == NULL) {
-        envp = environ;
-    }
-
-    err = proc_mgmt_bind_client();
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "proc_mgmt_bind_client");
-    }
-
-    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
-    assert(b != NULL);
-
-    // construct argument "string"
-    // \0-separated strings in contiguous character buffer
-    // this is needed, as flounder can't send variable-length arrays of strings
-    size_t argstrlen = 0;
-
-    for (int i = 0; argv[i] != NULL; i++) {
-        argstrlen += strlen(argv[i]) + 1;
-    }
-
-    char argstr[argstrlen];
-    size_t argstrpos = 0;
-    for (int i = 0; argv[i] != NULL; i++) {
-        strcpy(&argstr[argstrpos], argv[i]);
-        argstrpos += strlen(argv[i]);
-        argstr[argstrpos++] = '\0';
-    }
-    assert(argstrpos == argstrlen);
-
-    // repeat for environment
-    size_t envstrlen = 0;
-    for (int i = 0; envp[i] != NULL; i++) {
-        envstrlen += strlen(envp[i]) + 1;
-    }
-
-    char envstr[envstrlen];
-    size_t envstrpos = 0;
-    for (int i = 0; envp[i] != NULL; i++) {
-        strcpy(&envstr[envstrpos], envp[i]);
-        envstrpos += strlen(envp[i]);
-        envstr[envstrpos++] = '\0';
-    }
-    assert(envstrpos == envstrlen);
-
-    // make an unqualified path absolute using the $PATH variable
-    // TODO: implement search (currently assumes PATH is a single directory)
-    char *searchpath = getenv("PATH");
-    if (searchpath == NULL) {
-        searchpath = VFS_PATH_SEP_STR; // XXX: just put it in the root
-    }
-    size_t buflen = strlen(path) + strlen(searchpath) + 2;
-    char pathbuf[buflen];
-    if (path[0] != VFS_PATH_SEP) {
-        snprintf(pathbuf, buflen, "%s%c%s", searchpath, VFS_PATH_SEP, path);
-        pathbuf[buflen - 1] = '\0';
-        //vfs_path_normalise(pathbuf);
-        path = pathbuf;
-    }
-
-    struct capref domain_cap;
-    err = slot_alloc(&domain_cap);
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    if (capref_is_null(inheritcn_cap) && capref_is_null(argcn_cap)) {
-        err = b->rpc_tx_vtbl.spawn(b, core_id, path, argstr, argstrlen, envstr,
-                                   envstrlen, flags, &msgerr, &domain_cap);
-    } else {
-        err = b->rpc_tx_vtbl.spawn_with_caps(b, core_id, path, argstr,
-                                             argstrlen, envstr, envstrlen,
-                                             inheritcn_cap, argcn_cap, flags,
-                                             &msgerr, &domain_cap);
-    }
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "error sending spawn request to process manager");
-    } else if (err_is_fail(msgerr)) {
-        goto out;
-    }
-
-    if (ret_domain_cap != NULL) {
-        *ret_domain_cap = domain_cap;
-    }
-
-out:
-    return msgerr;
-    
-}
-
-/**
- * \brief Request the process manager to spawn a program on a specific core
- *
- * \param coreid          Core ID on which to spawn the program
- * \param path            Absolute path in the file system to an executable
- *                        image suitable for the given core
- * \param argv            Command-line arguments, NULL-terminated
- * \param envp            Optional environment, NULL-terminated
- *                        (pass NULL to inherit)
- * \param inheritcn_cap   Cap to a CNode containing capabilities to be inherited
- * \param argcn_cap       Cap to a CNode containing capabilities passed as
- *                        arguments
- * \param flags           Flags to spawn
- * \param ret_domain_cap  If non-NULL, filled in with domain cap of new domain
- *
- * \bug flags are currently ignored
- */
-errval_t proc_mgmt_spawn_program(coreid_t core_id, const char *path,
-                                 char *const argv[], char *const envp[],
-                                 uint8_t flags, struct capref *ret_domain_cap)
-{
-    return proc_mgmt_spawn_program_with_caps(core_id, path, argv, envp,
-                                             NULL_CAP, NULL_CAP, flags,
-                                             ret_domain_cap);
-}
-
-/**
- * \brief Request the process manager to span onto a new core.
- *
- * \param core_id ID of core to span onto.
- *
- * Blocks until the new dispatcher has established an interdispatcher connection
- * to the current one.
- */
-errval_t proc_mgmt_span(coreid_t core_id)
-{
-    coreid_t my_core_id = disp_get_core_id();
-    assert (core_id != my_core_id);
-
-    errval_t err, msgerr;
-    err = proc_mgmt_bind_client();
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "proc_mgmt_bind_client");
-    }
-    
-    struct span_domain_state *st;
-    err = domain_new_dispatcher_setup_only(core_id, &st);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "failed to setup new dispatcher");
-    }
-
-    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
-    assert(b != NULL);
-
-    err = b->rpc_tx_vtbl.span(b, cap_domainid, core_id, st->vroot, st->frame,
-                              &msgerr);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "error sending span request to process manager");
-    }
-
-    if (err_is_fail(msgerr)) {
-        return msgerr;
-    }
-
-    while(!st->initialized) {
-        event_dispatch(get_default_waitset());
-    }
-    free(st);
-
-    return SYS_ERR_OK;
-}
-
-/**
- * \brief Request the process manager to kill a domain
- *
- * \param domain_cap Domain ID cap for the victim
- */
-errval_t proc_mgmt_kill(struct capref domain_cap)
-{
-    errval_t err, msgerr;
-    err = proc_mgmt_bind_client();
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "proc_mgmt_bind_client");
-    }
-
-    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
-    assert(b != NULL);
-
-    err = b->rpc_tx_vtbl.kill(b, domain_cap, &msgerr);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "error sending kill request to process manager");
-    }
-
-    return msgerr;
-}
-
-/**
- * \brief Inform the process manager about exiting execution.
- */
-errval_t proc_mgmt_exit(uint8_t status)
-{
-    errval_t err = proc_mgmt_bind_client();
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
-    assert(b != NULL);
-
-    err = b->rpc_tx_vtbl.exit(b, cap_domainid, status);
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    return SYS_ERR_OK;
-}
-
-errval_t proc_mgmt_wait(struct capref domain_cap, uint8_t *status)
-{
-    errval_t err, msgerr;
-    err = proc_mgmt_bind_client();
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
-    assert(b != NULL);
-
-    err = b->rpc_tx_vtbl.wait(b, domain_cap, &msgerr, status);
-    if (err_is_fail(err)) {
-        USER_PANIC_ERR(err, "error sending wait request to process manager");
-    }
-
-    return msgerr;
-}
index 91c62af..08609e2 100644 (file)
@@ -1,30 +1,25 @@
 /**
  * \file
- * \brief Client for interacting with the spawn daemon on each core
+ * \brief Client for interacting with the process management server.
  */
 
 /*
- * Copyright (c) 2010, 2011, 2012, ETH Zurich.
+ * Copyright (c) 2017, 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, CAB F.78, Universitaetstr. 6, CH-8092 Zurich,
- * Attn: Systems Group.
+ * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
  */
 
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
 #include <barrelfish/barrelfish.h>
 #include <barrelfish/nameservice_client.h>
 #include <barrelfish/spawn_client.h>
-#include <barrelfish/cpu_arch.h>
-#include <barrelfish/proc_mgmt_client.h>
-#include <if/spawn_defs.h>
+#include <if/octopus_defs.h>
+#include <if/proc_mgmt_defs.h>
 #include <if/arrakis_defs.h>
 #include <if/monitor_defs.h>
-#include <if/octopus_defs.h>
+#include <if/spawn_defs.h>
 #include <vfs/vfs_path.h>
 
 // For spawn_program_on_all_cores
 #include <octopus/trigger.h> // for NOP_TRIGGER
 
 
-
-extern char **environ;
+struct proc_mgmt_bind_retst {
+    errval_t err;
+    struct proc_mgmt_binding *b;
+    bool present;
+};
 
 struct spawn_bind_retst {
     errval_t err;
@@ -47,6 +45,8 @@ struct arrakis_bind_retst {
     bool present;
 };
 
+extern char **environ;
+
 static void spawn_bind_cont(void *st, errval_t err, struct spawn_binding *b)
 {
     struct spawn_bind_retst *retst = st;
@@ -144,31 +144,398 @@ errval_t spawn_bind_iref(iref_t iref, struct spawn_binding **ret_client)
     return err;
 }
 
+
+static void error_handler(struct proc_mgmt_binding *b, errval_t err)
+{
+#if defined(__x86_64__) || defined(__i386__)
+    debug_printf("%p \n",  __builtin_return_address(0));
+#endif
+    debug_err(__FILE__, __func__, __LINE__, err,
+              "asynchronous error in proc_mgmt binding");
+    abort();
+}
+
+static void proc_mgmt_bind_cont(void *st, errval_t err,
+        struct proc_mgmt_binding *b)
+{
+    struct proc_mgmt_bind_retst *retst = (struct proc_mgmt_bind_retst*) st;
+    assert(retst != NULL);
+    assert(!retst->present);
+    retst->err = err;
+    retst->b = b;
+    retst->present = true;
+    b->st = retst;
+}
+
+static void proc_mgmt_accept_recv_handler(void *arg)
+{
+    struct proc_mgmt_lmp_binding *b = arg;
+    struct lmp_recv_msg msg = LMP_RECV_MSG_INIT;
+    struct capref cap;
+    errval_t err;
+
+    // try to retrieve a message from the channel
+    err = lmp_chan_recv(&b->chan, &msg, &cap);
+    if (err_is_fail(err)) {
+        if (err_no(err) == LIB_ERR_NO_LMP_MSG) {
+            // nothing there, re-register
+            struct event_closure recv_handler = {
+                .handler = proc_mgmt_accept_recv_handler,
+                .arg = b,
+            };
+            err = lmp_chan_register_recv(&b->chan, b->b.waitset, recv_handler);
+            b->b.error_handler(&b->b, err_push(err, LIB_ERR_CHAN_REGISTER_RECV));
+        } else {
+            // real error, report to user
+            b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_CHAN_RECV));
+        }
+        return;
+    }
+
+    // TODO(razvan): LMP_PROC_MGMT_ACCEPT ?
+    assert(b->chan.connstate == LMP_MONITOR_ACCEPT);
+    assert(!capref_is_null(cap));
+    b->chan.remote_cap = cap;
+    b->chan.connstate = LMP_CONNECTED;
+
+    /* allocate a new receive slot */
+    err = lmp_chan_alloc_recv_slot(&b->chan);
+    if (err_is_fail(err)) {
+        // XXX: report the error, but continue
+        b->b.error_handler(&b->b, err_push(err, LIB_ERR_LMP_ALLOC_RECV_SLOT));
+    }
+
+    /* Run the RX handler; has a side-effect of registering for receive events */
+    proc_mgmt_lmp_rx_handler(b);
+}
+
+static errval_t init_lmp_binding(struct proc_mgmt_lmp_binding *lmpb,
+                                 struct waitset *ws,
+                                 size_t buflen_words)
+{
+    errval_t err;
+
+    proc_mgmt_lmp_init(lmpb, ws);
+
+    /* allocate a cap slot for the new endpoint cap */
+    err = slot_alloc(&lmpb->chan.local_cap);
+    if (err_is_fail(err)) {
+        return err_push(err, LIB_ERR_SLOT_ALLOC);
+    }
+
+    /* allocate a local endpoint */
+    err = lmp_endpoint_create_in_slot(buflen_words, lmpb->chan.local_cap,
+                                      &lmpb->chan.endpoint);
+    if (err_is_fail(err)) {
+        // TODO(razvan): Free cap slot.
+        return err_push(err, LIB_ERR_ENDPOINT_CREATE);
+    }
+
+    /* allocate an initial receive slot */
+    err = lmp_chan_alloc_recv_slot(&lmpb->chan);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    /* setup error handler */
+    lmpb->b.error_handler = error_handler;
+
+    /* setup initial receive handlers */
+    // TODO(razvan): Don't think this is needed, but dunno for sure yet.
+    // lmpb->b.rx_vtbl = monitor_rx_vtbl;
+
+    // connect handlers
+    lmpb->b.change_waitset(&lmpb->b, lmpb->b.waitset);
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief Accept a new LMP binding to a proc mgmt client.
+ *
+ * Should only be used in the process manager.
+ *
+ * \param lmpb         Storage for binding state
+ * \param ws           Waitset for handling incoming messages
+ * \param buflen_words Size of incoming buffer, in number of words
+ */
+errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
+                                     struct waitset *ws,
+                                     size_t lmp_buflen_words)
+{
+    errval_t err = init_lmp_binding(lmpb, ws, lmp_buflen_words);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    lmpb->chan.connstate = LMP_MONITOR_ACCEPT;  // TODO(razvan): LMP_PROC_MGMT_ACCEPT?
+    lmpb->chan.remote_cap = NULL_CAP; // will be sent to us by the client
+
+    /* Register for receive notification on our special handler */
+    struct event_closure receive_handler = {
+        .handler = proc_mgmt_accept_recv_handler,
+        .arg = lmpb,
+    };
+    err = lmp_chan_register_recv(&lmpb->chan, ws, receive_handler);
+    if (err_is_fail(err)) {
+        return err;  // TODO(razvan): cleanup?
+    }
+
+    return SYS_ERR_OK;
+}
+
+
+/**
+ * \brief Initiate a new LMP binding to the process manager
+ *
+ * To be used by the monitor for setting up the privileged channel used for
+ * spawnd discovery.
+ * Requires an explicit remote endpoint cap allocated by the process manager.
+ *
+ * \param lmpb         Storage for binding state
+ * \param ep           Remote endpoint of the process manager
+ * \param ws           Waitset for handling incoming messages
+ * \param cont         Continuation for when binding completes or fails
+ * \param st           State passed to continuation function
+ * \param buflen_words Size of incoming buffer, in number of words
+ */
+errval_t proc_mgmt_client_lmp_bind(struct proc_mgmt_lmp_binding *lmpb,
+                                   struct capref ep,
+                                   proc_mgmt_bind_continuation_fn *cont,
+                                   void *st,
+                                   struct waitset *ws,
+                                   size_t lmp_buflen_words)
+{
+    errval_t err = init_lmp_binding(lmpb, ws, lmp_buflen_words);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    lmpb->chan.remote_cap = ep;
+
+    // Send the local endpoint cap to the process manager.
+    lmpb->chan.connstate = LMP_CONNECTED; /* pre-established */
+    err = lmp_chan_send0(&lmpb->chan, 0, lmpb->chan.local_cap);
+    if (err_is_fail(err)) {
+        // TODO(razvan): This, below.
+        /* XXX: I'm lazily assuming this can never fail with a transient error,
+         * since we only do it once at dispatcher startup. If not, we need to
+         * register and retry here */
+        assert(!lmp_err_is_transient(err));
+        return err;
+    }
+
+    /* Run the RX handler; has a side-effect of registering for receive events */
+    proc_mgmt_lmp_rx_handler(lmpb);
+
+    /* Run the continuation */
+    cont(st, SYS_ERR_OK, &lmpb->b);
+
+    return SYS_ERR_OK;
+}
+
+errval_t proc_mgmt_bind_client(void)
+{
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    if (b != NULL) {
+        return SYS_ERR_OK;
+    }
+
+    errval_t err;
+    iref_t iref;
+    // Try using nameserver to retrievew the proc mgmt iref.
+    err = nameservice_blocking_lookup("proc_mgmt", &iref);
+    if (err_is_fail(err)) {
+        return err;
+    }
+    
+    // Initiate bind.
+    struct proc_mgmt_bind_retst bindst = {
+        .present = false
+    };
+
+    err = proc_mgmt_bind(iref, proc_mgmt_bind_cont, &bindst,
+            get_default_waitset(), /*IDC_BIND_FLAG_RPC_CAP_TRANSFER*/IDC_BIND_FLAGS_DEFAULT);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "proc_mgmt_bind");
+    }
+
+    // Wait for bind completion.
+    while (!bindst.present) {
+        messages_wait_and_handle_next();
+    }
+
+    if (err_is_fail(bindst.err)) {
+        return bindst.err;
+    }
+
+    proc_mgmt_rpc_client_init(bindst.b);
+
+    set_proc_mgmt_binding(bindst.b);
+
+    return SYS_ERR_OK;
+}
+
+errval_t proc_mgmt_add_spawnd(iref_t iref, coreid_t core_id)
+{
+    errval_t err = proc_mgmt_bind_client();
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "proc_mgmt_bind_client");
+        return err;
+    }
+
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    assert(b != NULL);
+
+    err = b->tx_vtbl.add_spawnd(b, NOP_CONT, core_id, iref);
+    if (err_is_fail(err)) {
+        DEBUG_ERR(err, "add_spawnd");
+    }
+
+    return err;
+}
+
 /**
- * \brief Request the spawn daemon on a specific core to spawn a program
+ * \brief Request the process manager to spawn a program on a specific core
  *
- * \param coreid        Core ID on which to spawn the program
- * \param path          Absolute path in the file system to an executable image
- *                      suitable for the given core
- * \param argv          Command-line arguments, NULL-terminated
- * \param envp          Optional environment, NULL-terminated
- *                      (pass NULL to inherit)
- * \param inheritcn_cap Cap to a CNode containing capabilities to be inherited
- * \param argcn_cap     Cap to a CNode containing capabilities passed as
- *                      arguments
- * \param flags         Flags to spawn
- * \param domain_Cap  If non-NULL, filled in with domain cap of program
+ * \param coreid          Core ID on which to spawn the program
+ * \param path            Absolute path in the file system to an executable
+ *                        image suitable for the given core
+ * \param argv            Command-line arguments, NULL-terminated
+ * \param envp            Optional environment, NULL-terminated
+ *                        (pass NULL to inherit)
+ * \param inheritcn_cap   Cap to a CNode containing capabilities to be inherited
+ * \param argcn_cap       Cap to a CNode containing capabilities passed as
+ *                        arguments
+ * \param flags           Flags to spawn
+ * \param ret_domain_cap  If non-NULL, filled in with domain cap of new domain
  *
  * \bug flags are currently ignored
  */
-errval_t spawn_program_with_caps(coreid_t coreid, const char *path,
-                                 char *const argv[], char *const envp[],
+errval_t spawn_program_with_caps(coreid_t core_id, const char *path,
+                                 char *const argv[],
+                                 char *const envp[],
                                  struct capref inheritcn_cap,
-                                 struct capref argcn_cap, spawn_flags_t flags,
-                                 struct capref *domain_cap)
+                                 struct capref argcn_cap,
+                                 uint8_t flags,
+                                 struct capref *ret_domain_cap)
 {
-    return proc_mgmt_spawn_program_with_caps(coreid, path, argv, envp, inheritcn_cap, 
-                                             argcn_cap, flags, domain_cap);
+    errval_t err, msgerr;
+
+    // default to copying our environment
+    if (envp == NULL) {
+        envp = environ;
+    }
+
+    err = proc_mgmt_bind_client();
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "proc_mgmt_bind_client");
+    }
+
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    assert(b != NULL);
+
+    // construct argument "string"
+    // \0-separated strings in contiguous character buffer
+    // this is needed, as flounder can't send variable-length arrays of strings
+    size_t argstrlen = 0;
+
+    for (int i = 0; argv[i] != NULL; i++) {
+        argstrlen += strlen(argv[i]) + 1;
+    }
+
+    char argstr[argstrlen];
+    size_t argstrpos = 0;
+    for (int i = 0; argv[i] != NULL; i++) {
+        strcpy(&argstr[argstrpos], argv[i]);
+        argstrpos += strlen(argv[i]);
+        argstr[argstrpos++] = '\0';
+    }
+    assert(argstrpos == argstrlen);
+
+    // repeat for environment
+    size_t envstrlen = 0;
+    for (int i = 0; envp[i] != NULL; i++) {
+        envstrlen += strlen(envp[i]) + 1;
+    }
+
+    char envstr[envstrlen];
+    size_t envstrpos = 0;
+    for (int i = 0; envp[i] != NULL; i++) {
+        strcpy(&envstr[envstrpos], envp[i]);
+        envstrpos += strlen(envp[i]);
+        envstr[envstrpos++] = '\0';
+    }
+    assert(envstrpos == envstrlen);
+
+    // make an unqualified path absolute using the $PATH variable
+    // TODO: implement search (currently assumes PATH is a single directory)
+    char *searchpath = getenv("PATH");
+    if (searchpath == NULL) {
+        searchpath = VFS_PATH_SEP_STR; // XXX: just put it in the root
+    }
+    size_t buflen = strlen(path) + strlen(searchpath) + 2;
+    char pathbuf[buflen];
+    if (path[0] != VFS_PATH_SEP) {
+        snprintf(pathbuf, buflen, "%s%c%s", searchpath, VFS_PATH_SEP, path);
+        pathbuf[buflen - 1] = '\0';
+        //vfs_path_normalise(pathbuf);
+        path = pathbuf;
+    }
+
+    struct capref domain_cap;
+    err = slot_alloc(&domain_cap);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    if (capref_is_null(inheritcn_cap) && capref_is_null(argcn_cap)) {
+        err = b->rpc_tx_vtbl.spawn(b, core_id, path, argstr, argstrlen, envstr,
+                                   envstrlen, flags, &msgerr, &domain_cap);
+    } else {
+        err = b->rpc_tx_vtbl.spawn_with_caps(b, core_id, path, argstr,
+                                             argstrlen, envstr, envstrlen,
+                                             inheritcn_cap, argcn_cap, flags,
+                                             &msgerr, &domain_cap);
+    }
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "error sending spawn request to process manager");
+    } else if (err_is_fail(msgerr)) {
+        goto out;
+    }
+
+    if (ret_domain_cap != NULL) {
+        *ret_domain_cap = domain_cap;
+    }
+
+out:
+    return msgerr;
+    
+}
+
+/**
+ * \brief Request the process manager to spawn a program on a specific core
+ *
+ * \param coreid          Core ID on which to spawn the program
+ * \param path            Absolute path in the file system to an executable
+ *                        image suitable for the given core
+ * \param argv            Command-line arguments, NULL-terminated
+ * \param envp            Optional environment, NULL-terminated
+ *                        (pass NULL to inherit)
+ * \param inheritcn_cap   Cap to a CNode containing capabilities to be inherited
+ * \param argcn_cap       Cap to a CNode containing capabilities passed as
+ *                        arguments
+ * \param flags           Flags to spawn
+ * \param ret_domain_cap  If non-NULL, filled in with domain cap of new domain
+ *
+ * \bug flags are currently ignored
+ */
+errval_t spawn_program(coreid_t core_id, const char *path,
+                       char *const argv[], char *const envp[],
+                       uint8_t flags, struct capref *ret_domain_cap)
+{
+    return spawn_program_with_caps(core_id, path, argv, envp,
+                                   NULL_CAP, NULL_CAP, flags,
+                                   ret_domain_cap);
 }
 
 errval_t spawn_arrakis_program(coreid_t coreid, const char *path,
@@ -287,30 +654,6 @@ errval_t spawn_arrakis_program(coreid_t coreid, const char *path,
     return msgerr;
 }
 
-
-/**
- * \brief Request the spawn daemon on a specific core to spawn a program
- *
- * \param coreid Core ID on which to spawn the program
- * \param path   Absolute path in the file system to an executable image
- *                        suitable for the given core
- * \param argv   Command-line arguments, NULL-terminated
- * \param envp   Optional environment, NULL-terminated (pass NULL to inherit)
- * \param flags  Flags to spawn
- * \param ret_domain_cap If non-NULL, filled in with domain cap of program
- *
- * \bug flags are currently ignored
- */
-errval_t spawn_program(coreid_t coreid, const char *path,
-                       char *const argv[], char *const envp[],
-                       spawn_flags_t flags, struct capref* ret_domain_cap)
-{
-    return spawn_program_with_caps(coreid, path, argv, envp, NULL_CAP,
-                                   NULL_CAP, flags, ret_domain_cap);
-}
-
-
-
 /**
  * \brief Request a program be spawned on all cores in the system
  *
@@ -371,7 +714,7 @@ errval_t spawn_program_on_all_cores(bool same_core, const char *path,
             continue;
         }
 
-        err = proc_mgmt_spawn_program(c, path, argv, envp, flags, NULL);
+        err = spawn_program(c, path, argv, envp, flags, NULL);
         if (err_is_ok(err) && spawn_count != NULL) {
             *spawn_count += 1;
         }
@@ -399,39 +742,94 @@ errval_t spawn_binding(coreid_t coreid, struct spawn_binding **ret_client)
 }
 
 /**
- * \brief Kill a domain.
+ * \brief Request the process manager to span onto a new core.
+ *
+ * \param core_id ID of core to span onto.
+ *
+ * Blocks until the new dispatcher has established an interdispatcher connection
+ * to the current one.
  */
-errval_t spawn_kill(struct capref domain_cap)
+errval_t spawn_span(coreid_t core_id)
 {
-    return proc_mgmt_kill(domain_cap);
-}
+    coreid_t my_core_id = disp_get_core_id();
+    assert (core_id != my_core_id);
 
-errval_t spawn_wait_compat(uint8_t domainid,
-                           uint8_t *exitcode, bool nohang)
- {
-    errval_t err, reterr;
+    errval_t err, msgerr;
+    err = proc_mgmt_bind_client();
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "proc_mgmt_bind_client");
+    }
+    
+    struct span_domain_state *st;
+    err = domain_new_dispatcher_setup_only(core_id, &st);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "failed to setup new dispatcher");
+    }
 
-    err = bind_client(disp_get_core_id());
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    assert(b != NULL);
+
+    err = b->rpc_tx_vtbl.span(b, cap_domainid, core_id, st->vroot, st->frame,
+                              &msgerr);
     if (err_is_fail(err)) {
-        return err;
+        USER_PANIC_ERR(err, "error sending span request to process manager");
     }
-    struct spawn_binding *cl = get_spawn_binding(disp_get_core_id());
-    assert(cl != NULL);
 
-    err = cl->rpc_tx_vtbl.wait(cl, domainid, nohang, exitcode, &reterr);
+    if (err_is_fail(msgerr)) {
+        return msgerr;
+    }
+
+    while(!st->initialized) {
+        event_dispatch(get_default_waitset());
+    }
+    free(st);
+
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief Request the process manager to kill a domain
+ *
+ * \param domain_cap Domain ID cap for the victim
+ */
+errval_t spawn_kill(struct capref domain_cap)
+{
+    errval_t err, msgerr;
+    err = proc_mgmt_bind_client();
     if (err_is_fail(err)) {
-        return err;
+        USER_PANIC_ERR(err, "proc_mgmt_bind_client");
     }
 
-    return reterr;
- }
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    assert(b != NULL);
+
+    err = b->rpc_tx_vtbl.kill(b, domain_cap, &msgerr);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "error sending kill request to process manager");
+    }
+
+    return msgerr;
+}
 
 /**
- * \brief Exit this domain.
+ * \brief Inform the process manager about exiting execution.
  */
-errval_t spawn_exit(uint8_t exitcode)
+errval_t spawn_exit(uint8_t status)
 {
-    return proc_mgmt_exit(exitcode);
+    errval_t err = proc_mgmt_bind_client();
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    assert(b != NULL);
+
+    err = b->rpc_tx_vtbl.exit(b, cap_domainid, status);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    return SYS_ERR_OK;
 }
 
 /**
@@ -443,21 +841,57 @@ errval_t spawn_wait_coreid(coreid_t coreid, struct capref domain_cap,
     return spawn_wait_core(disp_get_core_id(), domain_cap, exitcode, nohang);
 }
 
+
 /**
  * \brief Wait for the termination of a domain on a remote core.
  */
 errval_t spawn_wait_core(coreid_t coreid, struct capref domain_cap,
                          uint8_t *exitcode, bool nohang)
 {
-    return proc_mgmt_wait(domain_cap, exitcode);
+    return spawn_wait(domain_cap, exitcode, nohang);
 }
 
+
 /**
  * \brief Wait for spawned proccess to exit on current core.
  */
-errval_t spawn_wait(struct capref domain_cap, uint8_t *exitcode, bool nohang)
+errval_t spawn_wait(struct capref domain_cap, uint8_t *status, bool nohang)
+{
+    errval_t err, msgerr;
+    err = proc_mgmt_bind_client();
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    struct proc_mgmt_binding *b = get_proc_mgmt_binding();
+    assert(b != NULL);
+
+    err = b->rpc_tx_vtbl.wait(b, domain_cap, &msgerr, status);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "error sending wait request to process manager");
+    }
+
+    return msgerr;
+}
+
+errval_t spawn_wait_compat(uint8_t domainid,
+                           uint8_t *exitcode, bool nohang)
 {
-    return spawn_wait_coreid(disp_get_core_id(), domain_cap, exitcode, nohang);
+    errval_t err, reterr;
+
+    err = bind_client(disp_get_core_id());
+    if (err_is_fail(err)) {
+        return err;
+    }
+    struct spawn_binding *cl = get_spawn_binding(disp_get_core_id());
+    assert(cl != NULL);
+
+    err = cl->rpc_tx_vtbl.wait(cl, domainid, nohang, exitcode, &reterr);
+    if (err_is_fail(err)) {
+        return err;
+    }
+
+    return reterr;
 }
 
 /**
index d3bc46b..bc13c3c 100644 (file)
@@ -15,7 +15,7 @@
 #include <string.h>
 
 #include <barrelfish/barrelfish.h>
-#include <barrelfish/proc_mgmt_client.h>
+#include <barrelfish/spawn_client.h>
 
 #define MAXPATH 256
 
@@ -42,13 +42,13 @@ int main(int argc, char *argv[])
         for (int i = 0; i < num_spawns; i++, core++) {
             core %= num_cores;
             /*
-              Signature for proc_mgmt_spawn_program is:
+              Signature for spawn_program is:
 
-              errval_t proc_mgmt_spawn_program(coreid_t coreid, const char *path,
+              errval_t spawn_program(coreid_t coreid, const char *path,
                char *const argv[], char *const envp[],
                 spawn_flags_t flags, struct capref *ret_domain_cap)
             */
-               err = proc_mgmt_spawn_program(core, path, argv, NULL, 0, 
+               err = spawn_program(core, path, argv, NULL, 0, 
                                                  &ret_domain_cap);
             if (err_is_fail(err)) {
                 DEBUG_ERR(err, "failed spawn %d on core %d", i, core);
index c262b1e..86d38bc 100644 (file)
@@ -18,7 +18,7 @@
 #include <sys/param.h>
 #include <monitor.h>
 #include <barrelfish/dispatch.h>
-#include <barrelfish/proc_mgmt_client.h>
+#include <barrelfish/spawn_client.h>
 #include <trace/trace.h>
 #include "send_cap.h"
 #include "capops.h"
index 631b888..4be1619 100644 (file)
@@ -17,7 +17,7 @@
 #include <barrelfish/dispatch.h>
 #include <barrelfish/deferred.h>
 #include <barrelfish/domain.h>
-#include <barrelfish/proc_mgmt_client.h>
+#include <barrelfish/spawn_client.h>
 #include <trace/trace.h>
 
 #ifdef __k1om__
index 37094bf..0b7cccc 100644 (file)
@@ -20,7 +20,7 @@
 #include <if/mem_defs.h>
 #include <if/proc_mgmt_defs.h>
 #include <barrelfish/monitor_client.h>
-#include <barrelfish/proc_mgmt_client.h>
+#include <barrelfish/spawn_client.h>
 #include <barrelfish/syscalls.h>
 #include <barrelfish_kpi/distcaps.h>
 #include <if/monitor_loopback_defs.h>
index d2c6c60..90e1739 100644 (file)
@@ -14,7 +14,6 @@
 
 #include <barrelfish/barrelfish.h>
 #include <barrelfish/nameservice_client.h>
-#include <barrelfish/proc_mgmt_client.h>
 #include <barrelfish/spawn_client.h>
 #include <if/monitor_defs.h>
 #include <if/proc_mgmt_defs.h>
index 91b8ee0..f6d7916 100644 (file)
@@ -21,7 +21,6 @@
 
 #include <barrelfish/spawn_client.h>
 #include <spawndomain/spawndomain.h>
-#include <barrelfish/proc_mgmt_client.h>
 #include <dist/barrier.h>
 
 #include "internal.h"
@@ -365,9 +364,8 @@ void spawn_app_domains(void)
                                      si.name, i);
 
                         struct capref ret_domain_cap;
-                        err = proc_mgmt_spawn_program(i, si.name,
-                                                      si.argv, environ, spawn_flags, 
-                                                      &ret_domain_cap);
+                        err = spawn_program(i, si.name, si.argv, environ, 
+                                            spawn_flags, &ret_domain_cap);
                         if (err_is_fail(err)) {
                             DEBUG_ERR(err, "spawn of %s failed", si.name);
                         }
@@ -380,9 +378,8 @@ void spawn_app_domains(void)
                 debug_printf("starting app %s on core %d\n", si.name, coreid);
 
                 struct capref ret_domain_cap;
-                err = proc_mgmt_spawn_program(coreid, si.name,
-                                              si.argv, environ, spawn_flags, 
-                                              &ret_domain_cap);
+                err = spawn_program(coreid, si.name, si.argv, environ, 
+                                    spawn_flags, &ret_domain_cap);
                 if (err_is_fail(err)) {
                     DEBUG_ERR(err, "spawn of %s failed", si.name);
                 }
index 46ce106..219b9f9 100644 (file)
@@ -16,7 +16,6 @@
 #include <barrelfish/barrelfish.h>
 #include <barrelfish/deferred.h>
 #include <barrelfish/sys_debug.h>
-#include <barrelfish/proc_mgmt_client.h>
 #include <barrelfish/spawn_client.h>
 #include <bench/bench.h>
 
@@ -136,9 +135,9 @@ int main(int argc, char **argv)
         } else if (strcmp("span", argv[2]) == 0) {
             // Process that spans domains
             if (disp_get_core_id() == 0) {
-                proc_mgmt_span(1);
+                spawn_span(1);
             } else {
-                proc_mgmt_span(0);
+                spawn_span(0);
             }
             while(true) {
                 event_dispatch(get_default_waitset());