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, 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];
24
25static struct bench_binding *binding;
26static coreid_t my_core_id;
27
28#define MAX_COUNT 1000
29
30struct timestamp {
31    cycles_t time0;
32    cycles_t time1;
33};
34static struct timestamp timestamps[MAX_COUNT];
35static int benchmark_type = 0;
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    switch(benchmark_type) {
67    case 0:
68        err = binding->tx_vtbl.fsb_payload32_1_request(binding, NOP_CONT, 1);
69        break;
70
71    case 1:
72        err = binding->tx_vtbl.fsb_payload32_2_request(binding, NOP_CONT, 1, 2);
73        break;
74
75    case 2:
76        err = binding->tx_vtbl.fsb_payload32_4_request(binding, NOP_CONT, 1, 2, 3, 4);
77        break;
78
79    case 3:
80        err = binding->tx_vtbl.fsb_payload32_8_request(binding, NOP_CONT, 1, 2, 3, 4, 5, 6, 7, 8);
81        break;
82
83    case 4:
84        err = binding->tx_vtbl.fsb_payload32_16_request(binding, NOP_CONT, 1, 2, 3, 4, 5, 6, 7, 8,
85                                                        9, 10, 11, 12, 13, 14, 15, 16);
86        break;
87
88    default:
89        printf("unknown benchmark type\n");
90        abort();
91        break;
92    }
93
94    assert(err_is_ok(err));
95}
96
97static void fsb_init_msg(struct bench_binding *b, coreid_t id)
98{
99    binding = b;
100    printf("Running flounder_stubs_payload32 between core %d and core %d\n", my_core_id, 1);
101    experiment();
102}
103
104static void fsb_payload32_1_reply(struct bench_binding *b,
105                               int32_t p0)
106{
107    experiment();
108}
109
110static void fsb_payload32_2_reply(struct bench_binding *b,
111                               int32_t p0, int32_t p1)
112{
113    experiment();
114}
115
116static void fsb_payload32_4_reply(struct bench_binding *b,
117                              int32_t payload0, int32_t payload1,
118                              int32_t payload2, int32_t payload3)
119{
120    experiment();
121}
122
123static void fsb_payload32_8_reply(struct bench_binding *b,
124                               int32_t p0, int32_t p1, int32_t p2, int32_t p3,
125                               int32_t p4, int32_t p5, int32_t p6, int32_t p7)
126{
127    experiment();
128}
129
130static void fsb_payload32_16_reply(struct bench_binding *b,
131                                int32_t p0, int32_t p1, int32_t p2, int32_t p3,
132                                int32_t p4, int32_t p5, int32_t p6, int32_t p7,
133                                int32_t p8, int32_t p9, int32_t p10, int32_t p11,
134                                int32_t p12, int32_t p13, int32_t p14, int32_t p15)
135{
136    experiment();
137}
138
139
140static void fsb_payload32_1_request(struct bench_binding *b,
141                              int32_t payload0)
142{
143    errval_t err;
144    err = b->tx_vtbl.fsb_payload32_1_reply(b, NOP_CONT, 1);
145    assert(err_is_ok(err));
146}
147
148static void fsb_payload32_2_request(struct bench_binding *b,
149                                 int32_t payload0, int32_t payload1)
150{
151    errval_t err;
152    err = b->tx_vtbl.fsb_payload32_2_reply(b, NOP_CONT, 1, 2);
153    assert(err_is_ok(err));
154}
155
156static void fsb_payload32_4_request(struct bench_binding *b,
157                              int32_t payload0, int32_t payload1,
158                              int32_t payload2, int32_t payload3)
159{
160    errval_t err;
161    err = b->tx_vtbl.fsb_payload32_4_reply(b, NOP_CONT, 1, 2, 3, 4);
162    assert(err_is_ok(err));
163}
164
165static void fsb_payload32_8_request(struct bench_binding *b,
166                                 int32_t payload0, int32_t payload1,
167                                 int32_t payload2, int32_t payload3,
168                                 int32_t payload4, int32_t payload5,
169                                 int32_t payload6, int32_t payload7)
170{
171    errval_t err;
172    err = b->tx_vtbl.fsb_payload32_8_reply(b, NOP_CONT, 1, 2, 3, 4, 5, 6, 7, 8);
173    assert(err_is_ok(err));
174}
175
176static void fsb_payload32_16_request(struct bench_binding *b,
177                                  int32_t payload0, int32_t payload1,
178                                  int32_t payload2, int32_t payload3,
179                                  int32_t payload4, int32_t payload5,
180                                  int32_t payload6, int32_t payload7,
181                                  int32_t payload8, int32_t payload9,
182                                  int32_t payload10, int32_t payload11,
183                                  int32_t payload12, int32_t payload13,
184                                  int32_t payload14, int32_t payload15)
185{
186    errval_t err;
187    err = b->tx_vtbl.fsb_payload32_16_reply(b, NOP_CONT, 1, 2, 3, 4, 5, 6, 7, 8,
188                                            9, 10, 11, 12, 13, 14, 15, 16);
189    assert(err_is_ok(err));
190}
191
192static struct bench_rx_vtbl rx_vtbl = {
193    .fsb_init_msg   = fsb_init_msg,
194    .fsb_payload32_1_request = fsb_payload32_1_request,
195    .fsb_payload32_2_request = fsb_payload32_2_request,
196    .fsb_payload32_4_request = fsb_payload32_4_request,
197    .fsb_payload32_8_request = fsb_payload32_8_request,
198    .fsb_payload32_16_request = fsb_payload32_16_request,
199    .fsb_payload32_1_reply = fsb_payload32_1_reply,
200    .fsb_payload32_2_reply = fsb_payload32_2_reply,
201    .fsb_payload32_4_reply = fsb_payload32_4_reply,
202    .fsb_payload32_8_reply = fsb_payload32_8_reply,
203    .fsb_payload32_16_reply = fsb_payload32_16_reply,
204};
205
206static void bind_cb(void *st, errval_t binderr, struct bench_binding *b)
207{
208    // copy my message receive handler vtable to the binding
209    b->rx_vtbl = rx_vtbl;
210
211    errval_t err;
212    err = b->tx_vtbl.fsb_init_msg(b, NOP_CONT, my_core_id);
213    assert(err_is_ok(err));
214}
215
216static void export_cb(void *st, errval_t err, iref_t iref)
217{
218    if (err_is_fail(err)) {
219        DEBUG_ERR(err, "export failed");
220        abort();
221    }
222
223    // register this iref with the name service
224    err = nameservice_register("fsb_server", iref);
225    if (err_is_fail(err)) {
226        DEBUG_ERR(err, "nameservice_register failed");
227        abort();
228    }
229}
230
231static errval_t connect_cb(void *st, struct bench_binding *b)
232{
233    // copy my message receive handler vtable to the binding
234    b->rx_vtbl = rx_vtbl;
235
236    // accept the connection
237    return SYS_ERR_OK;
238}
239
240int main(int argc, char *argv[])
241{
242    errval_t err;
243
244    /* Set my core id */
245    my_core_id = disp_get_core_id();
246    strcpy(my_name, argv[0]);
247
248    bench_init();
249
250    // Default first arg
251    if(argc == 1) {
252        argc = 2;
253        argv[1] = "0";
254    }
255
256    if (argc == 2) { /* bsp core */
257        benchmark_type = atoi(argv[1]);
258
259        /*
260          1. spawn domain,
261          2. setup a server,
262          3. wait for client to connect,
263          4. run experiment
264        */
265        char *xargv[] = {my_name, "dummy", "dummy", "dummy", NULL};
266        err = spawn_program(1, my_name, xargv, NULL,
267                            SPAWN_FLAGS_DEFAULT, NULL);
268        assert(err_is_ok(err));
269
270        /* Setup a server */
271        err = bench_export(NULL, export_cb, connect_cb, get_default_waitset(),
272                           IDC_BIND_FLAGS_DEFAULT);
273        assert(err_is_ok(err));
274    } else {
275        /* Connect to the server */
276        iref_t iref;
277
278        err = nameservice_blocking_lookup("fsb_server", &iref);
279        if (err_is_fail(err)) {
280            DEBUG_ERR(err, "nameservice_blocking_lookup failed");
281            abort();
282        }
283
284        err = bench_bind(iref, bind_cb, NULL,
285                         get_default_waitset(), IDC_BIND_FLAGS_DEFAULT);
286        if (err_is_fail(err)) {
287            DEBUG_ERR(err, "bind failed");
288            abort();
289        }
290    }
291
292    messages_handler_loop();
293}
294