1/**
2 * \file
3 * \brief Generic/base microbenchmark code.
4 *
5 * This file implements some (currently very primitive) services for
6 * running and printing the results of a set of microbenchmarks.
7 * Most of the benchmarks themselves are defined in the architecture-specific
8 * part, in arch_microbenchmarks.c.
9 */
10
11/*
12 * Copyright (c) 2007, 2008, 2009, ETH Zurich.
13 * All rights reserved.
14 *
15 * This file is distributed under the terms in the attached LICENSE file.
16 * If you do not find this file, copies can be found by writing to:
17 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
18 */
19
20#include <kernel.h>
21#include <stdio.h>
22#include <string.h>
23#include <microbenchmarks.h>
24#include <misc.h>
25
26static uint64_t divide_round(uint64_t quotient, uint64_t divisor)
27{
28    if ((quotient % divisor) * 2 >= divisor) {
29        // round up
30        return (quotient / divisor) + 1;
31    } else {
32        return (quotient / divisor);
33    }
34}
35
36static int microbench_print(struct microbench *mb, char *buf, size_t len)
37{
38    return snprintf(buf, len, "%" PRIu64 " ticks",
39                    divide_round(mb->result, MICROBENCH_ITERATIONS));
40}
41
42static int microbenchmarks_run(struct microbench *benchs, size_t nbenchs)
43{
44    for (size_t i = 0; i < nbenchs; i++) {
45        int                     r;
46        struct microbench       *mb;
47
48        mb = &benchs[i];
49        printk(LOG_NOTE, "Running benchmark %zu/%zu: %s\n", i + 1, nbenchs,
50               mb->name);
51        r = mb->run_func(mb);
52
53        if (r != 0) {
54            printk(LOG_ERR, "%s: Error %d running %s\n", __func__, r, mb->name);
55            return r;
56        }
57    }
58
59    return 0;
60}
61
62static int microbenchmarks_print_all(struct microbench *benchs, size_t nbenchs)
63{
64    int i, r;
65    struct microbench *mb;
66    char buf[64];
67
68    for (i = 0; i < nbenchs; i++) {
69        mb = &benchs[i];
70        r = microbench_print(mb, buf, sizeof(buf) - 1);
71        if (r <= 0 || r >= sizeof(buf)) {
72            /* FIXME: error handling */
73            return -1;
74        }
75        printf("%40s: %s\n", mb->name, buf);
76    }
77
78    return 0;
79}
80
81void microbenchmarks_run_all(void)
82{
83    microbenchmarks_run(arch_benchmarks, arch_benchmarks_size);
84
85    printf("\n------------------------ Statistics ------------------------\n");
86    microbenchmarks_print_all(arch_benchmarks, arch_benchmarks_size);
87    printf("------------------------------------------------------------\n\n");
88}
89