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