1/**
2 * \file
3 * \brief Flounder stubs
4 */
5
6/*
7 * Copyright (c) 2007, 2008, 2009, 2010, 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, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
13 */
14
15#include <stdio.h>
16#include <barrelfish/barrelfish.h>
17#include <string.h>
18#include <barrelfish/nameservice_client.h>
19#include <barrelfish/spawn_client.h>
20#include <bench/bench.h>
21#include <if/bench_defs.h>
22
23static char my_name[100];
24
25static struct bench_binding *binding;
26static coreid_t my_core_id;
27
28#define MAX_COUNT 100
29
30struct timestamp {
31    cycles_t time0;
32    cycles_t time1;
33};
34static struct timestamp timestamps[MAX_COUNT];
35
36static void experiment(void)
37{
38    errval_t err;
39    static bool flag = false;
40    static int i = 0;
41
42    // Experiment finished
43    if (i == MAX_COUNT - 1) {
44        timestamps[i].time1 = bench_tsc();
45
46        for (int j = MAX_COUNT / 10; j < MAX_COUNT; j++) {
47            printf("page %d took %"PRIuCYCLES"\n", j,
48                   timestamps[j].time1 - bench_tscoverhead() -
49                   timestamps[j].time0);
50        }
51
52        printf("client done\n");
53        return;
54    }
55
56    if (!flag) { // Start experiment
57        timestamps[i].time0 = bench_tsc();
58        flag = true;
59    } else { // Continue experiment
60        timestamps[i].time1 = bench_tsc();
61        timestamps[i+1].time0 = timestamps[i].time1;
62        i++;
63    }
64    err = binding->tx_vtbl.fsb_empty_request(binding, NOP_CONT);
65    assert(err_is_ok(err));
66}
67
68static void fsb_init_msg(struct bench_binding *b, coreid_t id)
69{
70    binding = b;
71    printf("Running flounder_stubs_empty between core %d and core %d\n", id, my_core_id);
72    experiment();
73}
74
75static void fsb_empty_reply(struct bench_binding *b)
76{
77    experiment();
78}
79
80static void fsb_empty_request(struct bench_binding *b)
81{
82    errval_t err;
83    err = b->tx_vtbl.fsb_empty_reply(b, NOP_CONT);
84    assert(err_is_ok(err));
85}
86
87static struct bench_rx_vtbl rx_vtbl = {
88    .fsb_init_msg   = fsb_init_msg,
89    .fsb_empty_request = fsb_empty_request,
90    .fsb_empty_reply = fsb_empty_reply,
91};
92
93static void bind_cb(void *st, errval_t binderr, struct bench_binding *b)
94{
95    // copy my message receive handler vtable to the binding
96    b->rx_vtbl = rx_vtbl;
97
98    // Send an init message
99    errval_t err;
100    err = b->tx_vtbl.fsb_init_msg(b, NOP_CONT, my_core_id);
101    assert(err_is_ok(err));
102}
103
104static void export_cb(void *st, errval_t err, iref_t iref)
105{
106    if (err_is_fail(err)) {
107        DEBUG_ERR(err, "export failed");
108        abort();
109    }
110
111    // register this iref with the name service
112    err = nameservice_register("fsb_server", iref);
113    if (err_is_fail(err)) {
114        DEBUG_ERR(err, "nameservice_register failed");
115        abort();
116    }
117}
118
119static errval_t connect_cb(void *st, struct bench_binding *b)
120{
121    // copy my message receive handler vtable to the binding
122    b->rx_vtbl = rx_vtbl;
123
124
125    // accept the connection
126    return SYS_ERR_OK;
127}
128
129int main(int argc, char *argv[])
130{
131    errval_t err;
132
133    /* Set my core id */
134    my_core_id = disp_get_core_id();
135    strcpy(my_name, argv[0]);
136
137    printf("entered\n");
138    bench_init();
139    printf("bench_init done\n");
140
141    if (argc == 1) { /* server */
142        /*
143          1. spawn domain,
144          2. setup a server,
145          3. wait for client to connect,
146          4. run experiment
147        */
148        char *xargv[] = {my_name, "dummy", NULL};
149        printf("spawning...\n");
150        err = spawn_program(1, my_name, xargv, NULL,
151                            SPAWN_FLAGS_DEFAULT, NULL);
152        assert(err_is_ok(err));
153
154        /* Setup a server */
155        err = bench_export(NULL, export_cb, connect_cb, get_default_waitset(),
156                           IDC_BIND_FLAGS_DEFAULT);
157        assert(err_is_ok(err));
158    } else {
159        /* Connect to the server */
160        iref_t iref;
161        printf("ns lookup\n");
162        err = nameservice_blocking_lookup("fsb_server", &iref);
163        if (err_is_fail(err)) {
164            DEBUG_ERR(err, "nameservice_blocking_lookup failed");
165            abort();
166        }
167        printf("bench_bind\n");
168        err = bench_bind(iref, bind_cb, NULL,
169                         get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
170        if (err_is_fail(err)) {
171            DEBUG_ERR(err, "bind failed");
172            abort();
173        }
174    }
175    printf("message_loop\n");
176    messages_handler_loop();
177}
178