1/**
2 * \file
3 * \brief Phase-change scalability benchmark
4 */
5
6/*
7 * Copyright (c) 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 <barrelfish/waitset.h>
18#include <barrelfish/resource_ctrl.h>
19#include <barrelfish/sys_debug.h>
20#include <bench/bench.h>
21
22struct workcnt {
23  uint64_t	cnt;
24} __attribute__ ((aligned (64)));
25
26static const char *my_manifest =
27    "B 1\n"                     // Normal phase
28    "B 1\n";                    // Other normal phase
29
30static int init_done = 1;
31static rsrcid_t my_rsrc_id;
32static struct thread_sem init_sem = THREAD_SEM_INITIALIZER;
33static struct thread_mutex init_lock = THREAD_MUTEX_INITIALIZER;
34static struct thread_cond init_cond = THREAD_COND_INITIALIZER;
35static struct workcnt workcnt[MAX_CPUS];
36
37static int remote_init(void *arg)
38{
39    errval_t err = rsrc_join(my_rsrc_id);
40    assert(err_is_ok(err));
41
42    thread_mutex_lock(&init_lock);
43    thread_sem_post(&init_sem);
44    thread_cond_wait(&init_cond, &init_lock);
45    thread_mutex_unlock(&init_lock);
46
47    for(;;) {
48        workcnt[disp_get_core_id()].cnt++;
49    }
50
51    return 0;
52}
53
54static void domain_spanned(void *arg, errval_t reterr)
55{
56    assert(err_is_ok(reterr));
57    init_done++;
58}
59
60int main(int argc, char *argv[])
61{
62    int my_core_id = disp_get_core_id();
63    errval_t err;
64    uint64_t tscperms;
65
66    if(argc < 4) {
67        printf("Usage: %s threads phase-delay timeout\n", argv[0]);
68    }
69    int nthreads = atoi(argv[1]);
70    int delay = atoi(argv[2]);
71    int timeout = atoi(argv[3]);
72
73    err = sys_debug_get_tsc_per_ms(&tscperms);
74    assert(err_is_ok(err));
75
76    bench_init();
77
78    // Submit manifest (derived from program)
79    err = rsrc_manifest(my_manifest, &my_rsrc_id);
80
81    /* Span domain to all cores */
82    for (int i = my_core_id + 1; i < nthreads + my_core_id; i++) {
83        err = domain_new_dispatcher(i, domain_spanned, NULL);
84        if (err_is_fail(err)) {
85            DEBUG_ERR(err, "failed to span domain");
86        }
87        assert(err_is_ok(err));
88    }
89
90    while(init_done < nthreads) {
91        thread_yield();
92    }
93
94    for (int i = my_core_id + 1; i < nthreads + my_core_id; i++) {
95        err = domain_thread_create_on(i, remote_init, NULL, NULL);
96        assert(err_is_ok(err));
97        thread_sem_wait(&init_sem);
98    }
99
100    thread_mutex_lock(&init_lock);
101    thread_cond_broadcast(&init_cond);
102    thread_mutex_unlock(&init_lock);
103
104    // Run benchmark
105    bool flip = false;
106    cycles_t begin = bench_tsc(), end = 0;
107    for(;;) {
108        if(delay != 0) {
109            flip = !flip;
110            err = rsrc_phase(my_rsrc_id, flip ? 1 : 0);
111            assert(err_is_ok(err));
112            end = bench_tsc();
113        }
114
115        // Let it cool down
116        do {
117            workcnt[disp_get_core_id()].cnt++;
118
119            // Stop when timeout is reached
120            if(bench_tsc() >= begin + (timeout * tscperms)) {
121                goto out;
122            }
123        } while(bench_tsc() < end + (delay * tscperms));
124    }
125
126 out:
127    for(int i = 0; i < nthreads; i++) {
128        printf("workcnt %d: %lu\n", i, workcnt[i].cnt);
129    }
130    printf("number of threads: %d, delay: %d\n", nthreads, delay);
131    printf("client done.\n");
132    return 0;
133}
134