First outline of a process management service server.
authorRazvan Damachi <razvan.damachi@gmail.com>
Thu, 1 Jun 2017 15:35:31 +0000 (17:35 +0200)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Thu, 31 Aug 2017 14:35:07 +0000 (16:35 +0200)
Right now, the server only has an "alloc_ep" call which the monitor will be
able to use to request connection for spawnd (for all monitors, all spawnds).
The server is not yet run by the monitor, but that should happen somewhere
along the initialization steps on the BSP core.

Signed-off-by: Razvan Damachi <razvan.damachi@gmail.com>

hake/menu.lst.x86_64
if/Hakefile
if/proc_mgmt.if [new file with mode: 0644]
include/barrelfish/proc_mgmt_client.h [new file with mode: 0644]
lib/barrelfish/Hakefile
lib/barrelfish/proc_mgmt_client.c [new file with mode: 0644]
platforms/Hakefile
usr/proc_mgmt/Hakefile [new file with mode: 0644]
usr/proc_mgmt/internal.h [new file with mode: 0644]
usr/proc_mgmt/main.c [new file with mode: 0644]
usr/proc_mgmt/service.c [new file with mode: 0644]

index 6161402..d7cb133 100644 (file)
@@ -28,6 +28,7 @@ modulenounzip /skb_ramfs.cpio.gz nospawn
 module  /x86_64/sbin/kaluga boot
 module  /x86_64/sbin/acpi boot
 module  /x86_64/sbin/spawnd boot
+module  /x86_64/sbin/proc_mgmt boot
 #bootapic-x86_64=1-15
 module  /x86_64/sbin/startd boot
 module /x86_64/sbin/routing_setup boot
index d674a4f..62efd03 100644 (file)
@@ -60,6 +60,7 @@
                "pci",
                "ping_pong",
                "pixels",
+               "proc_mgmt",
                "rcce",
                "replay",
                "routing",
diff --git a/if/proc_mgmt.if b/if/proc_mgmt.if
new file mode 100644 (file)
index 0000000..b957e34
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+interface proc_mgmt "Process management service" {
+  
+  // Allocate a new endpoint for a future connecting client.
+  rpc alloc_ep(out errval err, out cap ep);
+
+  // Spawn a new domain, returning its domainid cap.
+  rpc spawn(in coreid core,
+            in String path[2048],
+            in char argvbuf[argvbytes, 2048],
+            in char envbuf[envbytes, 2048],
+            in uint8 flags,
+            out errval err,
+            out cap domainid_cap);
+
+  // Span the caller to a new core.
+  rpc span(in cap domainid_cap,
+           in coreid core,
+           in cap vroot,
+           in cap disp_mem,
+           out errval err);
+
+  // Kill a domain for which the caller has a domainid cap.
+  rpc kill(in cap domainid_cap, out errval err);
+
+  // TODO(razvan): exit, wait, status, some other calls from spawn.if?
+};
diff --git a/include/barrelfish/proc_mgmt_client.h b/include/barrelfish/proc_mgmt_client.h
new file mode 100644 (file)
index 0000000..508372d
--- /dev/null
@@ -0,0 +1,29 @@
+/**
+ * \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;
+
+errval_t proc_mgmt_client_lmp_accept(struct proc_mgmt_lmp_binding *lmpb,
+               struct waitset *ws, size_t lmp_buflen_words);
+
+__END_DECLS
+
+#endif // BARRELFISH_PROC_MGMT_CLIENT_H
index 6d2d4e2..43e2e78 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",
+                    "idc_export.c", "nameservice_client.c", "msgbuf.c", "proc_mgmt_client.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",
diff --git a/lib/barrelfish/proc_mgmt_client.c b/lib/barrelfish/proc_mgmt_client.c
new file mode 100644 (file)
index 0000000..537e6dd
--- /dev/null
@@ -0,0 +1,146 @@
+/**
+ * \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/proc_mgmt_client.h>
+#include <if/proc_mgmt_defs.h>
+
+static void error_handler(struct proc_mgmt_binding *b, errval_t err)
+{
+#if defined(__x86_64__) || defined(__i386__)
+    debug_printf("%p %p %p %p\n", __builtin_return_address(0), __builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3));
+#endif
+    debug_err(__FILE__, __func__, __LINE__, err,
+              "error in proc_mgmt binding");
+    abort();
+}
+
+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;
+    }
+
+    // if we're the monitor, we might be waiting for the other side's cap
+    // TODO(razvan): Or the process manager, which for uses LMP_MONITOR_ACCEPT
+    // as well.
+    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.
+    // TODO(razvan): Whom is the receive slot for? Is it one of the spawnds?
+    // Or is it some arbitrary non-spawnd client domain? Need a way to tell.
+    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: 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 */
+    // lmpb->b.rx_vtbl = proc_mgmt_rx_vtbl;
+
+    // connect handlers
+    lmpb->b.change_waitset(&lmpb->b, lmpb->b.waitset);
+    return SYS_ERR_OK;
+}
+
+/**
+ * \brief Accept a new LMP binding in a client from the process manager.
+ *
+ * Should only be used in the process manager.
+ *
+ * \param pmcb         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;
+    }
+
+    // TODO(razvan): This should probably be something like LMP_PROC_MGMT_ACCEPT
+    lmpb->chan.connstate = LMP_MONITOR_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: cleanup?
+    }
+
+    return SYS_ERR_OK;
+}
index 01df2ec..915ad0a 100644 (file)
@@ -165,6 +165,7 @@ let bin_rcce_lu = [ "/sbin/" ++ f | f <- [
                           "init",
                           "skb",
                           "spawnd",
+                          "proc_mgmt",
                           "startd",
                           "mem_serv",
                           "monitor",
diff --git a/usr/proc_mgmt/Hakefile b/usr/proc_mgmt/Hakefile
new file mode 100644 (file)
index 0000000..48cb949
--- /dev/null
@@ -0,0 +1,37 @@
+--------------------------------------------------------------------------
+-- 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.
+--
+-- Hakefile for /usr/proc_mgmt
+--
+--------------------------------------------------------------------------
+
+[ build application { target = "proc_mgmt",
+                      cFiles = [ "main.c", "service.c" ],
+                      addLibraries = libDeps [ "skb", "dist", "lwip" ],
+                      flounderDefs = [ "monitor", "monitor_blocking"],
+                      flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
+                      flounderBindings = [ "proc_mgmt" ],
+                      architectures = [ "x86_64", "x86_32" ]
+                    },
+  build application { target = "proc_mgmt",
+                      cFiles = [ "main.c", "service.c" ],
+                      addLibraries = libDeps [ "skb", "dist", "lwip" ],
+                      flounderDefs = [ "monitor", "monitor_blocking"],
+                      flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
+                      flounderBindings = [ "proc_mgmt" ],
+                      architectures = [ "k1om" ]
+                    },
+  build application { target = "proc_mgmt",
+                      cFiles = [ "main.c", "service.c" ],
+                      addLibraries = libDeps [ "skb", "dist", "lwip" ],
+                      flounderDefs = [ "monitor", "monitor_blocking"],
+                      flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
+                      flounderBindings = [ "proc_mgmt" ],
+                      architectures = [ "armv7", "armv8" ]
+                    }
+]
diff --git a/usr/proc_mgmt/internal.h b/usr/proc_mgmt/internal.h
new file mode 100644 (file)
index 0000000..94fe5b7
--- /dev/null
@@ -0,0 +1,24 @@
+/**
+ * \file
+ * \brief Internal proc_mgmt functions.
+ */
+
+/*
+ * 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 PROC_MGMT_INTERNAL_H_
+#define PROC_MGMT_INTERNAL_H_
+
+#define SERVICE_BASENAME    "proc_mgmt" // the core ID is appended to this
+
+extern coreid_t my_core_id;
+
+errval_t start_service(void);
+
+#endif //PROC_MGMT_INTERNAL_H_
diff --git a/usr/proc_mgmt/main.c b/usr/proc_mgmt/main.c
new file mode 100644 (file)
index 0000000..37c8d3e
--- /dev/null
@@ -0,0 +1,39 @@
+/**
+ * \file
+ * \brief 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, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/dispatch.h>
+
+#include "internal.h"
+
+coreid_t my_core_id;
+
+int main(int argc, const char *argv[])
+{
+    errval_t err;
+
+    my_core_id = disp_get_core_id();
+
+    printf("proc_mgmt.%u up.\n", my_core_id);
+
+    err = start_service();
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "failed to start proc_mgmt service loop");
+    }
+
+    messages_handler_loop();
+}
diff --git a/usr/proc_mgmt/service.c b/usr/proc_mgmt/service.c
new file mode 100644 (file)
index 0000000..7c724d9
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * \file
+ * \brief Process management service.
+ */
+
+/*
+ * 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 <stdio.h>
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/nameservice_client.h>
+#include <barrelfish/proc_mgmt_client.h>
+#include <if/proc_mgmt_defs.h>
+
+#include "internal.h"
+
+static struct proc_mgmt_rpc_rx_vtbl rpc_rx_vtbl;
+
+static errval_t alloc_ep_handler(struct proc_mgmt_binding *b, errval_t *err,
+        struct capref *ep)
+{
+    struct proc_mgmt_lmp_binding *lmpb = (struct proc_mgmt_lmp_binding*) malloc(
+            sizeof(struct proc_mgmt_lmp_binding));
+    assert(lmpb != NULL);
+
+    *err = proc_mgmt_client_lmp_accept(lmpb, get_default_waitset(),
+            DEFAULT_LMP_BUF_WORDS);
+    if (err_is_ok(*err)) {
+        *ep = lmpb->chan.local_cap;
+
+        // struct proc_mgmt_state *st = (struct proc_mgmt_state*) malloc(
+        //         sizeof(struct proc_mgmt_state));
+        // assert(st != NULL);
+        // st->queue.head = st->queue.tail = NULL;
+
+        lmpb->b.rpc_rx_vtbl = rpc_rx_vtbl;
+        // lmpb->b.st = st;
+    } else {
+        free(lmpb);
+    }
+
+    return SYS_ERR_OK;
+}
+
+static errval_t spawn_handler(struct proc_mgmt_binding *b,
+                          coreid_t core,
+                          const char *path,
+                          const char *argvbuf,
+                          size_t argvbytes,
+                          const char *envbuf,
+                          size_t envbytes,
+                          uint8_t flags,
+                          errval_t *err,
+                          struct capref *domainid_cap)
+{
+    return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static errval_t span_handler(struct proc_mgmt_binding *b,
+                         struct capref domainid_cap,
+                         coreid_t core,
+                         struct capref vroot,
+                         struct capref disp_mem,
+                         errval_t *err)
+{
+    return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static errval_t kill_handler(struct proc_mgmt_binding *b,
+                         struct capref domainid_cap,
+                         errval_t *err)
+{
+    return LIB_ERR_NOT_IMPLEMENTED;
+}
+
+static struct proc_mgmt_rpc_rx_vtbl rpc_rx_vtbl = {
+    .alloc_ep_call = alloc_ep_handler,
+    .spawn_call = spawn_handler,
+    .span_call = span_handler,
+    .kill_call = kill_handler
+};
+
+static void export_cb(void *st, errval_t err, iref_t iref)
+{
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "export failed");
+    }
+
+    // construct name
+    char namebuf[32];
+    size_t len = snprintf(namebuf, sizeof(namebuf), "%s.%d", SERVICE_BASENAME,
+                          my_core_id);
+    assert(len < sizeof(namebuf));
+    namebuf[sizeof(namebuf) - 1] = '\0';
+
+    // register this iref with the name service
+    err = nameservice_register(namebuf, iref);
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err, "nameservice_register failed");
+    }
+}
+
+static errval_t connect_cb(void *st, struct proc_mgmt_binding *b)
+{
+    b->rpc_rx_vtbl = rpc_rx_vtbl;
+    return SYS_ERR_OK;
+}
+
+errval_t start_service(void)
+{
+    return proc_mgmt_export(NULL, export_cb, connect_cb, get_default_waitset(),
+            IDC_EXPORT_FLAGS_DEFAULT);
+}