1/**
2 * \file
3 * \brief UMP benchmarks
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, ETH Zurich.
8 * All rights reserved.
9 *
10 * This file is distributed under the terms in the attached LICENSE file.
11 * If you do not find this file, copies can be found by writing to:
12 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include "ump_bench.h"
16#include <string.h>
17#include <barrelfish/nameservice_client.h>
18#include <barrelfish/spawn_client.h>
19
20static coreid_t num_cores;
21static char my_name[100];
22
23struct bench_binding *array[MAX_CPUS] = {NULL};
24coreid_t my_core_id;
25
26static void ump_init_msg(struct bench_binding *b, coreid_t id)
27{
28    static int count = 0;
29    count++;
30    array[id] = b;
31
32    // All clients connected, run experiment
33    printf("%s: %d %d\n", __func__, count, num_cores);
34    if (count == num_cores) {
35        for (coreid_t i = 0; i < MAX_CPUS; i++) {
36            if (array[i]) {
37                experiment(i);
38            }
39        }
40
41        printf("client done\n");
42    }
43}
44
45static struct bench_rx_vtbl rx_vtbl = {
46    .ump_init_msg   = ump_init_msg,
47};
48
49static void bind_cb(void *st, errval_t binderr, struct bench_binding *b)
50{
51    errval_t err;
52    err = b->tx_vtbl.ump_init_msg(b, NOP_CONT, my_core_id);
53    assert(err_is_ok(err));
54
55    struct bench_ump_binding *bu = (struct bench_ump_binding*)b;
56    struct flounder_ump_state *fus = &bu->ump_state;
57    struct ump_chan *chan = &fus->chan;
58
59    struct ump_chan_state *send = &chan->send_chan;
60    struct ump_chan_state *recv = &chan->endpoint.chan;
61
62    /* Wait for and reply to msgs */
63    while (1) {
64        volatile struct ump_message *msg;
65        struct ump_control ctrl;
66        while (!(msg = ump_impl_recv(recv)));
67        ump_impl_free_message(msg);
68        while (!(msg = ump_impl_get_next(send, &ctrl)));
69        msg->header.control = ctrl;
70    }
71}
72
73static void export_cb(void *st, errval_t err, iref_t iref)
74{
75    if (err_is_fail(err)) {
76        DEBUG_ERR(err, "export failed");
77        abort();
78    }
79
80    // register this iref with the name service
81    err = nameservice_register("ump_server", iref);
82    if (err_is_fail(err)) {
83        DEBUG_ERR(err, "nameservice_register failed");
84        abort();
85    }
86}
87
88static errval_t connect_cb(void *st, struct bench_binding *b)
89{
90    // copy my message receive handler vtable to the binding
91    b->rx_vtbl = rx_vtbl;
92
93    // accept the connection
94    return SYS_ERR_OK;
95}
96
97int main(int argc, char *argv[])
98{
99    errval_t err;
100
101    /* Set my core id */
102    my_core_id = disp_get_core_id();
103    strcpy(my_name, argv[0]);
104
105    bench_init();
106
107    if (argc == 1) { /* bsp core */
108
109        /* 1. spawn domains,
110           2. setup a server,
111           3. wait for all clients to connect,
112           4. run experiments
113        */
114        // Spawn domains
115        char *xargv[] = {my_name, "dummy", NULL};
116        err = spawn_program_on_all_cores(false, xargv[0], xargv, NULL,
117                                         SPAWN_FLAGS_DEFAULT, NULL, &num_cores);
118        DEBUG_ERR(err, "spawn program on all cores (%"PRIuCOREID")", num_cores);
119        assert(err_is_ok(err));
120
121        /* Setup a server */
122        err = bench_export(NULL, export_cb, connect_cb, get_default_waitset(),
123                           IDC_BIND_FLAGS_DEFAULT);
124        assert(err_is_ok(err));
125    } else {
126        /* Connect to the server */
127        iref_t iref;
128
129        err = nameservice_blocking_lookup("ump_server", &iref);
130        if (err_is_fail(err)) {
131            DEBUG_ERR(err, "nameservice_blocking_lookup failed");
132            abort();
133        }
134
135        err = bench_bind(iref, bind_cb, NULL,
136                         get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
137        if (err_is_fail(err)) {
138            DEBUG_ERR(err, "bind failed");
139            abort();
140        }
141    }
142
143    messages_handler_loop();
144}
145