#define BENCH_IGNORE_WATERMARK 0XDEADBEEF
-#define BENCH_DUMP_OCTAVE 0
+#define BENCH_DUMP_OCTAVE 1
__BEGIN_DECLS
void bench_init(void);
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);
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"])
--- /dev/null
+##########################################################################
+# 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)
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"]) ],
#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);
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;
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) {
}
}
- 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;
++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);
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.
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)
};
struct pending_spawn {
- struct capref domain_cap;
+ struct domain_cap_node *cap_node;
struct spawn_binding *b;
coreid_t core_id;
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);
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:
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,
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)) {
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;
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);
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;
}
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");
+ }
}
}
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);
}
[ 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" ],
uint64_t domain_cap_hash;
struct capref rootcn_cap;
+ struct capref dispframe;
struct capref dcb;
struct cnoderef rootcn;
uint8_t exitcode;
}
}
+#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,
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;
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,
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);
}
--- /dev/null
+--------------------------------------------------------------------------
+-- 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"]) ]
+ }
+]
--- /dev/null
+/** \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;
+}