DIRTY benchmark commit
authorRazvan Damachi <razvan.damachi@gmail.com>
Wed, 2 Aug 2017 14:41:12 +0000 (16:41 +0200)
committerSimon Gerber <simon.gerber@inf.ethz.ch>
Thu, 31 Aug 2017 14:35:09 +0000 (16:35 +0200)
Signed-off-by: Razvan Damachi <razvan.damachi@gmail.com>

14 files changed:
include/bench/bench.h
lib/barrelfish/threads.c
tools/harness/machines/__init__.py
tools/harness/tests/proc_mgmt_test.py [new file with mode: 0644]
usr/proc_mgmt/Hakefile
usr/proc_mgmt/domain.c
usr/proc_mgmt/domain.h
usr/proc_mgmt/pending_clients.h
usr/proc_mgmt/service.c
usr/spawnd/Hakefile
usr/spawnd/ps.h
usr/spawnd/service.c
usr/tests/proc_mgmt_test/Hakefile [new file with mode: 0644]
usr/tests/proc_mgmt_test/main.c [new file with mode: 0644]

index 3f3bed4..c2c326d 100644 (file)
@@ -21,7 +21,7 @@
 
 #define BENCH_IGNORE_WATERMARK 0XDEADBEEF
 
-#define BENCH_DUMP_OCTAVE 0
+#define BENCH_DUMP_OCTAVE 1
 
 __BEGIN_DECLS
 void bench_init(void);
index 6eacf55..9511b28 100644 (file)
@@ -1285,13 +1285,14 @@ void threads_prepare_to_span(dispatcher_handle_t newdh)
         acquire_spinlock(&thread_slabs_spinlock);
 
         while (slab_freecount(&thread_slabs) < MAX_THREADS - 1) {
+            printf("HEP\n");
             struct capref frame;
             size_t size;
             void *buf;
             errval_t err;
 
             size_t blocksize = sizeof(struct thread) + tls_block_total_len;
-            err = vspace_mmu_aware_map(&thread_slabs_vm, blocksize,
+            err = vspace_mmu_aware_map(&thread_slabs_vm, 64 * blocksize,
                                        &buf, &size);
             if (err_is_fail(err)) {
                 slot_free(frame);
index f551512..2dd219e 100644 (file)
@@ -234,6 +234,7 @@ class Machine(object):
         m.add_module("monitor")
         m.add_module("ramfsd", ["boot"])
         m.add_module("skb", ["boot"])
+        m.add_module("proc_mgmt", ["boot"])
         m.add_module("spawnd", ["boot"])
         m.add_module("startd", ["boot"])
         m.add_module("/eclipseclp_ramfs.cpio.gz", ["nospawn"])
diff --git a/tools/harness/tests/proc_mgmt_test.py b/tools/harness/tests/proc_mgmt_test.py
new file mode 100644 (file)
index 0000000..aac7c38
--- /dev/null
@@ -0,0 +1,40 @@
+##########################################################################
+# 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.
+##########################################################################
+
+import datetime
+import tests
+from common import TestCommon
+from results import PassFailResult
+
+@tests.add_test
+class ProcMgmtTest(TestCommon):
+    '''Process management service API. Requires at least 2 cores.'''
+    name = "proc_mgmt_test"
+
+    def setup(self, build, machine, testdir):
+        super(ProcMgmtTest, self).setup(build, machine, testdir)
+        self.test_timeout_delta = datetime.timedelta(seconds=15*60)
+
+    def get_modules(self, build, machine):
+        modules = super(ProcMgmtTest, self).get_modules(build, machine)
+        n = 3
+        for i in range(n):
+            modules.add_module("proc_mgmt_test", ["core=3", str(i), str(n)])
+            # modules.add_module("proc_mgmt_test", ["core=3", "1"])
+        return modules
+
+    def get_finish_string(self):
+        return "TEST DONE"
+
+    def process_data(self, testdir, rawiter):
+        for line in rawiter:
+            if line.startswith("FAIL:"):
+                return PassFailResult(False)
+
+        return PassFailResult(True)
index 296f2f9..a12ea7a 100644 (file)
@@ -14,7 +14,7 @@
                       cFiles = [ "main.c", "service.c", "spawnd_state.c", 
                                  "domain.c" ],
                       addLibraries = libDeps [ "skb", "dist", "lwip",
-                                               "collections" ],
+                                               "collections", "bench" ],
                       flounderDefs = [ "monitor", "monitor_blocking" ],
                       flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]), 
                                             ("spawn",["rpcclient"]) ],
index 09f7125..15d6987 100644 (file)
 #define HASH_INDEX_BUCKETS 6151
 static collections_hash_table* domain_table = NULL;
 
-errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry)
+#define DOMAIN_CAP_REFILL_COUNT 128
+static struct domain_cap_node *domain_cap_list = NULL;
+static uint32_t free_domain_caps = 0;
+
+#define PROC_MGMT_BENCH 1
+#define PROC_MGMT_BENCH_MIN_RUNS 100
+
+#ifdef PROC_MGMT_BENCH
+#include <bench/bench.h>
+
+static inline cycles_t calculate_time(cycles_t tsc_start, cycles_t tsc_end)
+{
+    cycles_t result;
+    if (tsc_end < tsc_start) {
+        result = (LONG_MAX - tsc_start) + tsc_end - bench_tscoverhead();
+    } else {
+        result = (tsc_end - tsc_start - bench_tscoverhead());
+    }
+    return result;
+}
+
+static bench_ctl_t *hash_ctl;
+static uint64_t tscperus;
+#endif
+
+inline bool domain_should_refill_caps(void) {
+    return free_domain_caps == 0;
+}
+
+errval_t domain_prealloc_caps(void)
+{
+    for (size_t i = 0; i < DOMAIN_CAP_REFILL_COUNT; ++i) {
+        struct domain_cap_node *node = (struct domain_cap_node*) malloc(
+                sizeof(struct domain_cap_node));
+        errval_t err = slot_alloc(&node->domain_cap);
+        if (err_is_fail(err)) {
+            DEBUG_ERR(err, "slot_alloc domain_cap");
+            return err_push(err, PROC_MGMT_ERR_CREATE_DOMAIN_CAP);
+        }
+
+        err = cap_retype(node->domain_cap, cap_procmng, 0, ObjType_Domain, 0, 1);
+        if (err_is_fail(err)) {
+            DEBUG_ERR(err, "cap_retype domain_cap");
+            return err_push(err, PROC_MGMT_ERR_CREATE_DOMAIN_CAP);
+        }
+
+        err = domain_cap_hash(node->domain_cap, &node->hash);
+        if (err_is_fail(err)) {
+            return err;
+        }
+
+        node->next = domain_cap_list;
+        domain_cap_list = node;
+        ++free_domain_caps;
+    }
+
+    return SYS_ERR_OK;
+}
+
+struct domain_cap_node *next_cap_node(void)
+{
+    assert(domain_cap_list != NULL);
+    assert(free_domain_caps > 0);
+    
+    struct domain_cap_node *tmp = domain_cap_list;
+    domain_cap_list = domain_cap_list->next;
+    --free_domain_caps;
+    
+    return tmp;
+}
+
+errval_t domain_new(struct domain_cap_node *cap_node,
+                    struct domain_entry **ret_entry)
 {
     assert(ret_entry != NULL);
 
@@ -29,7 +101,7 @@ errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry)
         return LIB_ERR_MALLOC_FAIL;
     }
 
-    entry->domain_cap = domain_cap;
+    entry->cap_node = cap_node;
     entry->status = DOMAIN_STATUS_NIL;
     memset(entry->spawnds, 0, sizeof(entry->spawnds));
     entry->num_spawnds_running = 0;
@@ -37,6 +109,20 @@ errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry)
     entry->waiters = NULL;
 
     if (domain_table == NULL) {
+#ifdef PROC_MGMT_BENCH
+        bench_init();
+
+        hash_ctl = calloc(1, sizeof(*hash_ctl));
+        hash_ctl->mode = BENCH_MODE_FIXEDRUNS;
+        hash_ctl->result_dimensions = 1;
+        hash_ctl->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+        hash_ctl->data = calloc(hash_ctl->min_runs * hash_ctl->result_dimensions,
+                               sizeof(*hash_ctl->data));
+
+        errval_t err = sys_debug_get_tsc_per_ms(&tscperus);
+        assert(err_is_ok(err));
+        tscperus /= 1000;
+#endif
         collections_hash_create_with_buckets(&domain_table, HASH_INDEX_BUCKETS,
                                              NULL);
         if (domain_table == NULL) {
@@ -44,13 +130,7 @@ errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry)
         }
     }
 
-    uint64_t key;
-    errval_t err = domain_cap_hash(entry->domain_cap, &key);
-    if (err_is_fail(err)) {
-        return err;
-    }
-
-    collections_hash_insert(domain_table, key, entry);
+    collections_hash_insert(domain_table, cap_node->hash, entry);
 
     *ret_entry = entry;
 
@@ -91,10 +171,10 @@ void domain_run_on_core(struct domain_entry *entry, coreid_t core_id)
     ++entry->num_spawnds_resources;
 }
 
-errval_t domain_spawn(struct capref domain_cap, coreid_t core_id)
+errval_t domain_spawn(struct domain_cap_node *cap_node, coreid_t core_id)
 {
     struct domain_entry *entry = NULL;
-    errval_t err = domain_new(domain_cap, &entry);
+    errval_t err = domain_new(cap_node, &entry);
     if (err_is_fail(err)) {
         if (entry != NULL) {
             free(entry);
index 2383fff..14d3051 100644 (file)
@@ -32,8 +32,15 @@ struct domain_waiter {
     struct domain_waiter *next;
 };
 
+struct domain_cap_node {
+    struct capref domain_cap;
+    uint64_t hash;
+
+    struct domain_cap_node *next;
+};
+
 struct domain_entry {
-    struct capref domain_cap;   // Unique domain ID cap.
+    struct domain_cap_node *cap_node;
     enum domain_status status;  // Current domain state.
 
     struct spawnd_state *spawnds[MAX_COREID];  // Spawnds running this domain.
@@ -45,12 +52,17 @@ struct domain_entry {
     uint8_t exit_status;
 };
 
-errval_t domain_new(struct capref domain_cap, struct domain_entry **ret_entry);
+bool domain_should_refill_caps(void);
+errval_t domain_prealloc_caps(void);
+struct domain_cap_node *next_cap_node(void);
+
+errval_t domain_new(struct domain_cap_node *cap_node,
+                    struct domain_entry **ret_entry);
 errval_t domain_get_by_cap(struct capref domain_cap,
                            struct domain_entry **ret_entry);
 void domain_run_on_core(struct domain_entry *entry, coreid_t core_id);
 
-errval_t domain_spawn(struct capref domain_cap, coreid_t core_id);
+errval_t domain_spawn(struct domain_cap_node *cap_node, coreid_t core_id);
 errval_t domain_can_span(struct capref domain_cap, coreid_t core_id);
 errval_t domain_span(struct capref domain_cap, coreid_t core_id);
 static inline void domain_stop_pending(struct domain_entry *entry)
index 9199ef5..360a11c 100644 (file)
@@ -31,7 +31,7 @@ enum ClientType {
 };
 
 struct pending_spawn {
-    struct capref domain_cap;
+    struct domain_cap_node *cap_node;
 
        struct spawn_binding *b;
        coreid_t core_id;
index 83d82fd..ae1a673 100644 (file)
@@ -59,8 +59,42 @@ static void add_spawnd_handler_non_monitor(struct proc_mgmt_binding *b,
 
 static bool cleanup_request_sender(struct msg_queue_elem *m);
 
+
+#define PROC_MGMT_BENCH 1
+#define PROC_MGMT_BENCH_MIN_RUNS 100
+
+#ifdef PROC_MGMT_BENCH
+#include <bench/bench.h>
+
+static inline cycles_t calculate_time(cycles_t tsc_start, cycles_t tsc_end)
+{
+    cycles_t result;
+    if (tsc_end < tsc_start) {
+        result = (LONG_MAX - tsc_start) + tsc_end - bench_tscoverhead();
+    } else {
+        result = (tsc_end - tsc_start - bench_tscoverhead());
+    }
+    return result;
+}
+
+static bench_ctl_t *req_ctl_1;
+static bench_ctl_t *req_ctl_2;
+static bench_ctl_t *req_ctl_3;
+static bench_ctl_t *req_ctl_4;
+static bench_ctl_t *req_ctl_5;
+static bench_ctl_t *resp_ctl;
+static uint64_t tscperus;
+#endif
+
 static void spawn_reply_handler(struct spawn_binding *b, errval_t spawn_err)
 {
+#ifdef PROC_MGMT_BENCH
+    cycles_t tsc_start, tsc_end;
+    cycles_t result;
+
+    tsc_start = bench_tsc();
+#endif
+
     struct pending_client *cl =
             (struct pending_client*) spawnd_state_dequeue_recv(b->st);
 
@@ -78,20 +112,32 @@ static void spawn_reply_handler(struct spawn_binding *b, errval_t spawn_err)
             spawn = (struct pending_spawn*) cl->st;
             err = spawn_err;
             if (err_is_ok(spawn_err)) {
-                err = domain_spawn(spawn->domain_cap, spawn->core_id);
+                err = domain_spawn(spawn->cap_node, spawn->core_id);
                 if (cl->type == ClientType_Spawn) {
                     resp_err = cl->b->tx_vtbl.spawn_response(cl->b, NOP_CONT,
                                                              err,
-                                                             spawn->domain_cap);
+                                                             spawn->cap_node->domain_cap);
                 } else {
                     resp_err = cl->b->tx_vtbl.spawn_with_caps_response(cl->b,
                                                                        NOP_CONT,
                                                                        err,
-                                                                       spawn->domain_cap);
+                                                                       spawn->cap_node->domain_cap);
                 }
             }
 
             free(spawn);
+
+#ifdef PROC_MGMT_BENCH
+            tsc_end = bench_tsc();
+            result = calculate_time(tsc_start, tsc_end);
+
+            if (resp_ctl != NULL && bench_ctl_add_run(resp_ctl, &result)) {
+                bench_ctl_dump_analysis(resp_ctl, 0, "proc_mgmt_resp",
+                                        tscperus);
+                bench_ctl_destroy(resp_ctl);
+                resp_ctl = NULL;
+            }
+#endif
             break;
 
         case ClientType_Span:
@@ -215,7 +261,7 @@ static bool spawn_request_sender(struct msg_queue_elem *m)
     if (with_caps) {
         err = spawn->b->tx_vtbl.spawn_with_caps_request(spawn->b, NOP_CONT,
                                                         cap_procmng,
-                                                        spawn->domain_cap,
+                                                        spawn->cap_node->domain_cap,
                                                         spawn->path,
                                                         spawn->argvbuf,
                                                         spawn->argvbytes,
@@ -226,10 +272,10 @@ static bool spawn_request_sender(struct msg_queue_elem *m)
                                                         spawn->flags);
     } else {
         err = spawn->b->tx_vtbl.spawn_request(spawn->b, NOP_CONT, cap_procmng,
-                                              spawn->domain_cap, spawn->path,
-                                              spawn->argvbuf, spawn->argvbytes,
-                                              spawn->envbuf, spawn->envbytes,
-                                              spawn->flags);
+                                              spawn->cap_node->domain_cap,
+                                              spawn->path, spawn->argvbuf,
+                                              spawn->argvbytes, spawn->envbuf,
+                                              spawn->envbytes, spawn->flags);
     }
 
     if (err_is_fail(err)) {
@@ -324,30 +370,81 @@ static errval_t spawn_handler_common(struct proc_mgmt_binding *b,
                                      struct capref inheritcn_cap,
                                      struct capref argcn_cap, uint8_t flags)
 {
+#ifdef PROC_MGMT_BENCH
+    cycles_t tsc_start, tsc_end;
+    cycles_t result;
+
+    tsc_start = bench_tsc();
+#endif
     if (!spawnd_state_exists(core_id)) {
         return PROC_MGMT_ERR_INVALID_SPAWND;
     }
+#ifdef PROC_MGMT_BENCH
+    tsc_end = bench_tsc();
+    result = calculate_time(tsc_start, tsc_end);
+
+    if (req_ctl_1 != NULL && bench_ctl_add_run(req_ctl_1, &result)) {
+        bench_ctl_dump_analysis(req_ctl_1, 0, "proc_mgmt_req 1", tscperus);
+        bench_ctl_destroy(req_ctl_1);
+        req_ctl_1 = NULL;
+    }
+#endif
 
+#ifdef PROC_MGMT_BENCH
+    tsc_start = bench_tsc();
+#endif
     struct spawnd_state *spawnd = spawnd_state_get(core_id);
     assert(spawnd != NULL);
     struct spawn_binding *cl = spawnd->b;
     assert(cl != NULL);
+#ifdef PROC_MGMT_BENCH
+    tsc_end = bench_tsc();
+    result = calculate_time(tsc_start, tsc_end);
 
-    struct capref domain_cap;
-    errval_t err = slot_alloc(&domain_cap);
-    if (err_is_fail(err)) {
-        DEBUG_ERR(err, "slot_alloc domain_cap");
-        return err_push(err, PROC_MGMT_ERR_CREATE_DOMAIN_CAP);
+    if (req_ctl_2 != NULL && bench_ctl_add_run(req_ctl_2, &result)) {
+        bench_ctl_dump_analysis(req_ctl_2, 0, "proc_mgmt_req 2", tscperus);
+        bench_ctl_destroy(req_ctl_2);
+        req_ctl_2 = NULL;
     }
-    err = cap_retype(domain_cap, cap_procmng, 0, ObjType_Domain, 0, 1);
-    if (err_is_fail(err)) {
-        DEBUG_ERR(err, "cap_retype domain_cap");
-        return err_push(err, PROC_MGMT_ERR_CREATE_DOMAIN_CAP);
+#endif
+
+#ifdef PROC_MGMT_BENCH
+    tsc_start = bench_tsc();
+#endif
+    errval_t err;
+    if (domain_should_refill_caps()) {
+        err = domain_prealloc_caps();
+        if (err_is_fail(err)) {
+            return err_push(err, PROC_MGMT_ERR_CREATE_DOMAIN_CAP);
+        }
+    }
+
+    struct domain_cap_node *cap_node = next_cap_node();
+
+    // struct capref domain_cap;
+    // errval_t err = slot_alloc(&domain_cap);
+    // if (err_is_fail(err)) {
+    //     DEBUG_ERR(err, "slot_alloc domain_cap");
+    //     return err_push(err, PROC_MGMT_ERR_CREATE_DOMAIN_CAP);
+    // }
+#ifdef PROC_MGMT_BENCH
+    tsc_end = bench_tsc();
+    result = calculate_time(tsc_start, tsc_end);
+
+    if (req_ctl_3 != NULL && bench_ctl_add_run(req_ctl_3, &result)) {
+        bench_ctl_dump_analysis(req_ctl_3, 0, "proc_mgmt_req 3", tscperus);
+        bench_ctl_destroy(req_ctl_3);
+        req_ctl_3 = NULL;
     }
+#endif
 
+#ifdef PROC_MGMT_BENCH
+    tsc_start = bench_tsc();
+#endif
     struct pending_spawn *spawn = (struct pending_spawn*) malloc(
             sizeof(struct pending_spawn));
-    spawn->domain_cap = domain_cap;
+    spawn->cap_node = cap_node;
+    // spawn->domain_cap = domain_cap;
     spawn->b = cl;
     spawn->core_id = core_id;
     spawn->path = path;
@@ -371,7 +468,6 @@ static errval_t spawn_handler_common(struct proc_mgmt_binding *b,
     msg->cont = spawn_request_sender;
 
     err = spawnd_state_enqueue_send(spawnd, msg);
-
     if (err_is_fail(err)) {
         DEBUG_ERR(err, "enqueuing spawn request");
         free(spawn);
@@ -379,6 +475,17 @@ static errval_t spawn_handler_common(struct proc_mgmt_binding *b,
         free(msg);
     }
 
+#ifdef PROC_MGMT_BENCH
+    tsc_end = bench_tsc();
+    result = calculate_time(tsc_start, tsc_end);
+
+    if (req_ctl_5 != NULL && bench_ctl_add_run(req_ctl_5, &result)) {
+        bench_ctl_dump_analysis(req_ctl_5, 0, "proc_mgmt_req 5", tscperus);
+        bench_ctl_destroy(req_ctl_5);
+        req_ctl_5 = NULL;
+    }
+#endif
+
     return SYS_ERR_OK;
 }
 
@@ -391,14 +498,12 @@ static void spawn_handler(struct proc_mgmt_binding *b, coreid_t core_id,
     err = spawn_handler_common(b, ClientType_Spawn, core_id, path, argvbuf,
                                argvbytes, envbuf, envbytes, NULL_CAP, NULL_CAP,
                                flags);
-    if (err_is_ok(err)) {
-        // Will respond to client when we get the reply from spawnd.
-        return;
-    }
 
-    resp_err = b->tx_vtbl.spawn_response(b, NOP_CONT, err, NULL_CAP);
-    if (err_is_fail(resp_err)) {
-        DEBUG_ERR(resp_err, "failed to send spawn_response");
+    if (err_is_fail(err)) {
+        resp_err = b->tx_vtbl.spawn_response(b, NOP_CONT, err, NULL_CAP);
+        if (err_is_fail(resp_err)) {
+            DEBUG_ERR(resp_err, "failed to send spawn_response");
+        }
     }
 }
 
@@ -677,6 +782,63 @@ static errval_t connect_cb(void *st, struct proc_mgmt_binding *b)
 
 errval_t start_service(void)
 {
+    errval_t err;
+#ifdef PROC_MGMT_BENCH
+    bench_init();
+
+    req_ctl_1 = calloc(1, sizeof(*req_ctl_1));
+    req_ctl_1->mode = BENCH_MODE_FIXEDRUNS;
+    req_ctl_1->result_dimensions = 1;
+    req_ctl_1->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+    req_ctl_1->data = calloc(req_ctl_1->min_runs * req_ctl_1->result_dimensions,
+                           sizeof(*req_ctl_1->data));
+
+    req_ctl_2 = calloc(1, sizeof(*req_ctl_2));
+    req_ctl_2->mode = BENCH_MODE_FIXEDRUNS;
+    req_ctl_2->result_dimensions = 1;
+    req_ctl_2->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+    req_ctl_2->data = calloc(req_ctl_2->min_runs * req_ctl_2->result_dimensions,
+                           sizeof(*req_ctl_2->data));
+
+    req_ctl_3 = calloc(1, sizeof(*req_ctl_3));
+    req_ctl_3->mode = BENCH_MODE_FIXEDRUNS;
+    req_ctl_3->result_dimensions = 1;
+    req_ctl_3->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+    req_ctl_3->data = calloc(req_ctl_3->min_runs * req_ctl_3->result_dimensions,
+                           sizeof(*req_ctl_3->data));
+
+    req_ctl_4 = calloc(1, sizeof(*req_ctl_4));
+    req_ctl_4->mode = BENCH_MODE_FIXEDRUNS;
+    req_ctl_4->result_dimensions = 1;
+    req_ctl_4->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+    req_ctl_4->data = calloc(req_ctl_4->min_runs * req_ctl_4->result_dimensions,
+                           sizeof(*req_ctl_4->data));
+
+    req_ctl_5 = calloc(1, sizeof(*req_ctl_5));
+    req_ctl_5->mode = BENCH_MODE_FIXEDRUNS;
+    req_ctl_5->result_dimensions = 1;
+    req_ctl_5->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+    req_ctl_5->data = calloc(req_ctl_5->min_runs * req_ctl_5->result_dimensions,
+                           sizeof(*req_ctl_5->data));
+
+    resp_ctl = calloc(1, sizeof(*resp_ctl));
+    resp_ctl->mode = BENCH_MODE_FIXEDRUNS;
+    resp_ctl->result_dimensions = 1;
+    resp_ctl->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+    resp_ctl->data = calloc(resp_ctl->min_runs * resp_ctl->result_dimensions,
+                            sizeof(*resp_ctl->data));
+
+    err = sys_debug_get_tsc_per_ms(&tscperus);
+    assert(err_is_ok(err));
+    tscperus /= 1000;
+#endif
+
+    err = domain_prealloc_caps();
+    if (err_is_fail(err)) {
+        USER_PANIC_ERR(err_push(err, PROC_MGMT_ERR_CREATE_DOMAIN_CAP),
+                       "domain_prealloc_caps in start_service");
+    }
+
     return proc_mgmt_export(NULL, export_cb, connect_cb, get_default_waitset(),
             IDC_EXPORT_FLAGS_DEFAULT);
 }
index 47a3b02..92900a0 100644 (file)
@@ -13,7 +13,7 @@
 [ build application { target = "spawnd",
                       cFiles = [ "main.c", "service.c", "ps.c" ],
                       addLibraries = libDeps [ "spawndomain", "elf", "trace", "skb",
-                                               "dist", "vfs", "lwip" ],
+                                               "dist", "vfs", "lwip", "bench" ],
                       flounderDefs = [ "monitor", "monitor_blocking" ],
                       flounderExtraDefs = [ ("monitor_blocking",["rpcclient"]) ],
                       flounderBindings = [ "spawn" ],
index cf88fde..739d119 100644 (file)
@@ -38,6 +38,7 @@ struct ps_entry {
     uint64_t domain_cap_hash;
     
     struct capref rootcn_cap;
+    struct capref dispframe;
     struct capref dcb;
     struct cnoderef rootcn;
     uint8_t exitcode;
index 0706aae..bec61c5 100644 (file)
@@ -392,6 +392,27 @@ reply:
     }
 }
 
+#define PROC_MGMT_BENCH 1
+#define PROC_MGMT_BENCH_MIN_RUNS 100
+
+#ifdef PROC_MGMT_BENCH
+#include <bench/bench.h>
+
+static inline cycles_t calculate_time(cycles_t tsc_start, cycles_t tsc_end)
+{
+    cycles_t result;
+    if (tsc_end < tsc_start) {
+        result = (LONG_MAX - tsc_start) + tsc_end - bench_tscoverhead();
+    } else {
+        result = (tsc_end - tsc_start - bench_tscoverhead());
+    }
+    return result;
+}
+
+static bench_ctl_t *ctl;
+static uint64_t tscperus;
+#endif
+
 static void spawn_request_handler(struct spawn_binding *b,
                                   struct capref procmng_cap,
                                   struct capref domain_cap, const char *path,
@@ -399,6 +420,12 @@ static void spawn_request_handler(struct spawn_binding *b,
                                   const char *envbuf, size_t envbytes,
                                   uint8_t flags)
 {
+#ifdef PROC_MGMT_BENCH
+    cycles_t tsc_start, tsc_end;
+    cycles_t result;
+
+    tsc_start = bench_tsc();
+#endif
 
     errval_t err, reply_err;
     struct capability ret;
@@ -423,6 +450,17 @@ reply:
     if (err_is_fail(reply_err)) {
         DEBUG_ERR(err, "failed to send spawn_reply");
     }
+
+#ifdef PROC_MGMT_BENCH
+    tsc_end = bench_tsc();
+    result = calculate_time(tsc_start, tsc_end);
+
+    if (ctl != NULL && bench_ctl_add_run(ctl, &result)) {
+        bench_ctl_dump_analysis(ctl, 0, "spawnd", tscperus);
+        bench_ctl_destroy(ctl);
+        ctl = NULL;
+    }
+#endif
 }
 
 static void span_request_handler(struct spawn_binding *b,
@@ -913,6 +951,21 @@ static errval_t connect_cb(void *st, struct spawn_binding *b)
 
 errval_t start_service(void)
 {
+#ifdef PROC_MGMT_BENCH
+    bench_init();
+
+    ctl = calloc(1, sizeof(*ctl));
+    ctl->mode = BENCH_MODE_FIXEDRUNS;
+    ctl->result_dimensions = 1;
+    ctl->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+    ctl->data = calloc(ctl->min_runs * ctl->result_dimensions,
+                       sizeof(*ctl->data));
+
+    errval_t err = sys_debug_get_tsc_per_ms(&tscperus);
+    assert(err_is_ok(err));
+    tscperus /= 1000;
+#endif
+
     return spawn_export(NULL, export_cb, connect_cb, get_default_waitset(),
                          IDC_EXPORT_FLAGS_DEFAULT);
 }
diff --git a/usr/tests/proc_mgmt_test/Hakefile b/usr/tests/proc_mgmt_test/Hakefile
new file mode 100644 (file)
index 0000000..8558d67
--- /dev/null
@@ -0,0 +1,20 @@
+--------------------------------------------------------------------------
+-- 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 proc_mgmt_test
+-- 
+--------------------------------------------------------------------------
+
+[
+build application { target = "proc_mgmt_test",
+                  cFiles = [ "main.c" ],
+                  addLibraries = libDeps [ "bench", "vfs" ],
+                  flounderDefs = [ "proc_mgmt" ],
+                  flounderExtraDefs = [ ("proc_mgmt",["rpcclient"]) ]
+                 }
+]
diff --git a/usr/tests/proc_mgmt_test/main.c b/usr/tests/proc_mgmt_test/main.c
new file mode 100644 (file)
index 0000000..82e6904
--- /dev/null
@@ -0,0 +1,207 @@
+/** \file
+ *  \brief Process Management test.
+ */
+
+/*
+ * 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 <stdlib.h>
+
+#include <barrelfish/barrelfish.h>
+#include <barrelfish/deferred.h>
+#include <barrelfish/proc_mgmt_client.h>
+#include <bench/bench.h>
+
+#define PROC_MGMT_BENCH 1
+#define PROC_MGMT_BENCH_MIN_RUNS 120
+
+int my_id;
+// int total_ids;
+
+static void test_spawn(coreid_t core_id, char *argv[],
+                          struct capref *ret_domain_cap)
+{
+       assert(ret_domain_cap != NULL);
+
+       errval_t err = proc_mgmt_spawn_program(core_id,
+                                                  "/x86_64/sbin/proc_mgmt_test",
+                                                  argv, NULL, 0, ret_domain_cap);
+       if (err_is_ok(err)) {
+               // printf("OK: my_id=%i, spawn(%u, proc_mgmt_test)\n", my_id, core_id);
+       } else {
+               // printf("FAIL: spawn(%u, proc_mgmt_test), err=%s\n", core_id,
+               //         err_getstring(err));
+       }
+}
+
+// static void test_span(coreid_t core_id)
+// {
+//     errval_t err = proc_mgmt_span(core_id);
+//     if (err_is_ok(err)) {
+//             printf("OK: span(%u)\n", core_id);
+//     } else {
+//             printf("FAIL: span(%u), err=%s\n", core_id, err_getstring(err));
+//     }
+// }
+
+// static void test_kill(struct capref domain_cap)
+// {
+//     errval_t err = proc_mgmt_kill(domain_cap);
+//     if (err_is_ok(err)) {
+//             printf("OK: kill\n");
+//     } else {
+//             printf("FAIL: kill, err=%s\n", err_getstring(err));
+//     }
+// }
+
+// static void test_wait(struct capref domain_cap)
+// {
+//     uint8_t code;
+//     errval_t err = proc_mgmt_wait(domain_cap, &code);
+//     if (err_is_ok(err)) {
+//             printf("OK: wait, code=%u\n", code);
+//     } else {
+//             printf("FAIL: wait, err=%s\n", err_getstring(err));
+//     }
+// }
+
+static inline cycles_t calculate_time(cycles_t tsc_start, cycles_t tsc_end)
+{
+    cycles_t result;
+    if (tsc_end < tsc_start) {
+        result = (LONG_MAX - tsc_start) + tsc_end - bench_tscoverhead();
+    } else {
+        result = (tsc_end - tsc_start - bench_tscoverhead());
+    }
+    return result;
+}
+
+int main(int argc, char **argv)
+{
+       if (argc == 3) {
+               bench_init();
+               
+               cycles_t tsc_start, tsc_end;
+       cycles_t result;
+       uint64_t tscperus;
+       
+       bench_ctl_t *ctl = calloc(1, sizeof(*ctl));
+           ctl->mode = BENCH_MODE_FIXEDRUNS;
+           ctl->result_dimensions = 1;
+           ctl->min_runs = PROC_MGMT_BENCH_MIN_RUNS;
+        ctl->data = calloc(ctl->min_runs * ctl->result_dimensions,
+                              sizeof(*ctl->data));
+
+               errval_t err = sys_debug_get_tsc_per_ms(&tscperus);
+           assert(err_is_ok(err));
+           tscperus /= 1000;
+
+               coreid_t target_core = 0;//strcmp(argv[1], "1") == 0 ? 1 : 2;
+               char *spawn_argv[] = { "proc_mgmt_test", "noop", NULL };
+               my_id = atoi(argv[1]);
+        struct capref domain_cap;
+               // total_ids = atoi(argv[2]);
+
+        barrelfish_usleep((0 - 10 * my_id) * 1000 * 1000);
+
+           // ctl = bench_ctl_init(BENCH_MODE_FIXEDRUNS, 1, 100);
+           do {
+               // debug_printf("BEFORE test_spawn\n");
+               tsc_start = bench_tsc();
+
+                       test_spawn(target_core, spawn_argv, &domain_cap);
+                       // test_wait(domain_cap);
+
+               tsc_end = bench_tsc();
+               result = calculate_time(tsc_start, tsc_end);
+
+                       barrelfish_usleep(2 * 1000 * 1000);
+           }while (!bench_ctl_add_run(ctl, &result));
+           // } while (true);
+
+           bench_ctl_dump_analysis(ctl, 0, "client", tscperus);
+
+       bench_ctl_destroy(ctl);
+
+               barrelfish_usleep(5 * 1000 * 1000);
+               while (true);
+
+               printf("TEST DONE\n");
+       } else {
+               // for(;;) {
+  //           errval_t err = event_dispatch(get_default_waitset());
+  //           if(err_is_fail(err)) {
+  //                   USER_PANIC_ERR(err, "event_dispatch");
+  //           }
+  //       }
+       }
+
+       // printf("HELLO from proc_mgmt_test, argc=%u\n", argc);
+       // // errval_t err;
+       // if (argc == 1) {
+       //      struct capref domain_cap_0;
+       //      char *argv_0[] = { "proc_mgmt_test", "1", NULL };
+       //      test_spawn(0, argv_0, &domain_cap_0);
+       //      barrelfish_usleep(5*1000*1000);
+       //      // while (true);
+       //      test_kill(domain_cap_0);
+       //      test_wait(domain_cap_0);
+       //      // barrelfish_usleep(0 * 1*1*1);
+
+       //      struct capref domain_cap_1;
+       //      char *argv_1[] = { "proc_mgmt_test", "1", "2", NULL };
+       //      test_spawn(1, argv_1, &domain_cap_1);
+       //      test_wait(domain_cap_1);
+
+       //      printf("TEST DONE\n");
+       //      // barrelfish_usleep(5*1000*1000);
+
+       //      // err = proc_mgmt_kill(domain_cap);
+       //      // if (err_is_fail(err)) {
+       //      //      USER_PANIC_ERR(err, "failed to kill proc_mgmt_test");
+       //      // }
+
+       //      // uint8_t status;
+       //      // err = proc_mgmt_wait(domain_cap, &status);
+       //      // printf("2nd proc_mgmt_test finished with status %u\n", status);
+       // } else if (argc == 2) {
+       //      // test_span(disp_get_core_id() == 0 ? 1 : 0);
+
+       //      // // struct capability ret;
+       //      // // err = debug_cap_identify(cap_domainid, &ret);
+       //      // // if (err_is_fail(err)) {
+       //      // //   USER_PANIC_ERR(err, "failed to identify cap_domainid");
+       //      // // }
+       //      // // assert(ret.type == ObjType_Domain);
+       //      // // printf("proc_mgmt_test: cap_domainid = { .coreid=%u, .core_local_id=%u "
+       //      // //      "}\n", ret.u.domain.coreid, ret.u.domain.core_local_id);
+
+       //      // // coreid_t other_core = disp_get_core_id() == 0 ? 1 : 0;
+       //      // // err = proc_mgmt_span(other_core);//domain_new_dispatcher(other_core, span_cb, NULL);
+       //      // // if (err_is_fail(err)) {
+       //      // //   USER_PANIC_ERR(err, "failed to span proc_mgmt_test on core %u\n",
+       //      // //                      other_core);
+       //      // // }
+
+       //      // // barrelfish_usleep(5*1000*1000);
+       //      // // printf("Main dispatcher exiting...\n");
+
+       //      for(;;) {
+ //            errval_t err = event_dispatch(get_default_waitset());
+ //            if(err_is_fail(err)) {
+ //                    USER_PANIC_ERR(err, "event_dispatch");
+ //            }
+ //        }
+       // } else {
+       //      // barrelfish_usleep(5 * 1000 * 1000);
+       //      // We'll just exit normally here, spawner should be waiting for us.
+       // }
+
+    return 0;
+}