1/** \file
2 *  \brief Tracing example application
3 */
4
5/*
6 * Copyright (c) 2010-2013, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16
17#include <barrelfish/barrelfish.h>
18#include <trace/trace.h>
19#include <trace_definitions/trace_defs.h>
20
21// Enable to benchmark the tracing framework.
22#define TRACE_EXAMPLE_BENCHMARK 0
23
24static void after_prepare(void *arg);
25
26static volatile bool finished;
27
28static errval_t init_tracing(void)
29{
30    trace_reset_all();
31
32    debug_printf("after trace reset\n");
33
34    // Tell the trace system when to start and stop.  We can also
35    // provide an overriding maximum duration (in cycles) as the last parameter.
36    return trace_control(TRACE_EVENT(TRACE_SUBSYS_XMPL,
37                                    TRACE_EVENT_XMPL_START, 0),
38                        TRACE_EVENT(TRACE_SUBSYS_XMPL,
39                                    TRACE_EVENT_XMPL_STOP, 0),
40                        0);
41}
42
43static void start_tracing(void)
44{
45    // start the trace going by providing the start event
46    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_START, 0);
47}
48
49static void stop_tracing(void)
50{
51    // stop the trace by providing the stop event
52    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_STOP, 0);
53}
54
55
56#if TRACE_EXAMPLE_BENCHMARK
57
58#define NUM_EVENTS 1000
59
60static void benchmark(void)
61{
62    uint64_t times[NUM_EVENTS];
63
64    int i = 0;
65    for (i=0; i < NUM_EVENTS; i++) {
66        uint64_t start = rdtsc();
67        trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV1, i);
68        uint64_t end = rdtsc();
69        times[i] = end-start;
70    }
71
72    printf("Call times:\n");
73    for (i=0; i < NUM_EVENTS; i++) {
74        printf("%" PRIu64 "\n", times[i]);
75    }
76    printf("Call time end.\n");
77
78}
79
80#endif
81
82// This callback is invoked when the flushing process of the tracing framework
83// is finished, so that you can continue your operations.
84static void callback(void *arg)
85{
86    debug_printf("callback invoked\n");
87
88    finished = true;
89}
90
91static void dump_trace(void)
92{
93    // dump the trace on the output.  We can copy and paste it
94    // to use in Aquarium.
95
96    debug_printf("the trace dump\n");
97
98    // Let the trace framework decide where to flush to
99    trace_flush(MKCLOSURE(callback, NULL));
100
101    debug_printf("finished trace dump\n");
102
103}
104
105static void do_stuff(void)
106{
107    // generate our own traces
108
109#if TRACE_EXAMPLE_BENCHMARK
110
111    benchmark();
112
113#else
114
115    trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 0);
116
117    trace_set_subsys_enabled(TRACE_SUBSYS_KERNEL, false);
118
119    trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 1);
120
121    trace_set_subsys_enabled(TRACE_SUBSYS_KERNEL, true);
122
123    trace_event(TRACE_SUBSYS_KERNEL, TRACE_EVENT_KERNEL_BZERO, 2);
124
125    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV1, 1);
126
127    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV2, 2);
128
129    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV1, 3);
130
131    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV2, 4);
132
133    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV1, 10);
134
135    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV2, 11);
136
137    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV1, 12);
138
139    trace_event(TRACE_SUBSYS_XMPL, TRACE_EVENT_XMPL_EV2, 13);
140
141#endif
142}
143
144// Callback that is invoked after the tracing framework
145// has been prepared.
146static void after_prepare(void *arg)
147{
148    debug_printf("after_prepare starts");
149
150    start_tracing();
151
152    debug_printf("we are tracing now\n");
153
154    // do stuff to generate traces
155    do_stuff();
156
157    stop_tracing();
158
159    // flush the trace buffer
160    dump_trace();
161
162}
163
164int main(int argc, char *argv[])
165{
166#ifndef CONFIG_TRACE
167    // bail - no tracing support
168    printf("%.*s: Error, no tracing support, cannot start xmpl-trace\n",
169           DISP_NAME_LEN, disp_name());
170    printf("%.*s: recompile with trace = TRUE in build/hake/Config.hs\n",
171           DISP_NAME_LEN, disp_name());
172    return -1;
173#endif
174
175    errval_t err;
176
177    debug_printf("starting\n");
178
179    // Enable this line if you want to flush automatically.
180    // trace_set_autoflush(true);
181
182    finished = false;
183
184    err = init_tracing();
185    if (err_is_fail(err)) {
186        DEBUG_ERR(err, "initialising tracing");
187        return EXIT_FAILURE;
188    }
189
190    // Make sure all subsystems get logged.
191    trace_set_all_subsys_enabled(true);
192
193    debug_printf("after init tracing\n");
194
195    // Prepare the tracing framework. This is optional.
196    trace_prepare(MKCLOSURE(after_prepare, NULL));
197
198    while(!finished) {
199        // Make sure this program is not exited before everything
200        // is completed.
201        event_dispatch_non_block(get_default_waitset());
202        thread_yield_dispatcher(NULL_CAP);
203    }
204
205    return EXIT_SUCCESS;
206}
207