1/**
2 * \file
3 * \brief Flounder stubs buffer
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, Haldeneggsteig 4, 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];
24static uint8_t buffer;
25
26static struct bench_binding *binding;
27static coreid_t my_core_id;
28
29#define MAX_COUNT 1000
30
31struct timestamp {
32    cycles_t time0;
33    cycles_t time1;
34};
35static struct timestamp timestamps[MAX_COUNT];
36
37static void experiment(void)
38{
39    errval_t err;
40    static bool flag = false;
41    static int i = 0;
42
43    // Experiment finished
44    if (i == MAX_COUNT - 1) {
45        timestamps[i].time1 = bench_tsc();
46
47        for (int j = MAX_COUNT / 10; j < MAX_COUNT; j++) {
48            printf("page %d took %"PRIuCYCLES"\n", j,
49                   timestamps[j].time1 - bench_tscoverhead() -
50                   timestamps[j].time0);
51        }
52
53        printf("client done\n");
54        return;
55    }
56
57    if (!flag) { // Start experiment
58        timestamps[i].time0 = bench_tsc();
59        flag = true;
60    } else { // Continue experiment
61        timestamps[i].time1 = bench_tsc();
62        timestamps[i+1].time0 = timestamps[i].time1;
63        i++;
64    }
65
66    err = binding->tx_vtbl.fsb_buffer_request(binding, NOP_CONT, &buffer, 1);
67    assert(err_is_ok(err));
68}
69
70static void fsb_init_msg(struct bench_binding *b, coreid_t id)
71{
72    binding = b;
73    printf("Running flounder_stubs_buffer between core %d and core %d\n", my_core_id, 1);
74    experiment();
75}
76
77static void fsb_buffer_reply(struct bench_binding *b, uint8_t *payload, size_t size)
78{
79    experiment();
80    free(payload);
81}
82
83static void fsb_buffer_request(struct bench_binding *b, uint8_t *payload, size_t size)
84{
85    errval_t err;
86    err = b->tx_vtbl.fsb_buffer_reply(b, NOP_CONT, &buffer, 1);
87    assert(err_is_ok(err));
88    free(payload);
89}
90
91static struct bench_rx_vtbl rx_vtbl = {
92    .fsb_init_msg   = fsb_init_msg,
93    .fsb_buffer_request = fsb_buffer_request,
94    .fsb_buffer_reply = fsb_buffer_reply,
95};
96
97static void bind_cb(void *st, errval_t binderr, struct bench_binding *b)
98{
99    // copy my message receive handler vtable to the binding
100    b->rx_vtbl = rx_vtbl;
101
102    errval_t err;
103    err = b->tx_vtbl.fsb_init_msg(b, NOP_CONT, my_core_id);
104    assert(err_is_ok(err));
105}
106
107static void export_cb(void *st, errval_t err, iref_t iref)
108{
109    if (err_is_fail(err)) {
110        DEBUG_ERR(err, "export failed");
111        abort();
112    }
113
114    // register this iref with the name service
115    err = nameservice_register("fsb_server", iref);
116    if (err_is_fail(err)) {
117        DEBUG_ERR(err, "nameservice_register failed");
118        abort();
119    }
120}
121
122static errval_t connect_cb(void *st, struct bench_binding *b)
123{
124    // copy my message receive handler vtable to the binding
125    b->rx_vtbl = rx_vtbl;
126
127    // accept the connection
128    return SYS_ERR_OK;
129}
130
131int main(int argc, char *argv[])
132{
133    errval_t err;
134
135    /* Set my core id */
136    my_core_id = disp_get_core_id();
137    strcpy(my_name, argv[0]);
138
139    bench_init();
140
141    if (argc == 1) { /* bsp core */
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        err = spawn_program(1, my_name, xargv, NULL,
150                            SPAWN_FLAGS_DEFAULT, NULL);
151        assert(err_is_ok(err));
152
153        /* Setup a server */
154        err = bench_export(NULL, export_cb, connect_cb, get_default_waitset(),
155                           IDC_BIND_FLAGS_DEFAULT);
156        assert(err_is_ok(err));
157    } else {
158        /* Connect to the server */
159        iref_t iref;
160
161        err = nameservice_blocking_lookup("fsb_server", &iref);
162        if (err_is_fail(err)) {
163            DEBUG_ERR(err, "nameservice_blocking_lookup failed");
164            abort();
165        }
166
167        err = bench_bind(iref, bind_cb, NULL,
168                         get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
169        if (err_is_fail(err)) {
170            DEBUG_ERR(err, "bind failed");
171            abort();
172        }
173    }
174
175    messages_handler_loop();
176}
177