atrace.cpp revision 7b5170b249c1d312cfe3b5658b6c140b2a48226f
1fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* 2fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * Copyright (C) 2012 The Android Open Source Project 3fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * 4fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * Licensed under the Apache License, Version 2.0 (the "License"); 5fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * you may not use this file except in compliance with the License. 6fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * You may obtain a copy of the License at 7fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * 8fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * http://www.apache.org/licenses/LICENSE-2.0 9fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * 10fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * Unless required by applicable law or agreed to in writing, software 11fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * distributed under the License is distributed on an "AS IS" BASIS, 12fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * See the License for the specific language governing permissions and 14fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis * limitations under the License. 15fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis */ 16fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 17fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <errno.h> 18fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <fcntl.h> 19fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <signal.h> 20fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdarg.h> 21fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdbool.h> 22fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdio.h> 23fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdlib.h> 24fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <sys/sendfile.h> 25fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <time.h> 267b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis#include <zlib.h> 27fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 28fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Command line options */ 29fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic int g_traceDurationSeconds = 5; 30fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceSchedSwitch = false; 31cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool g_traceCpuFrequency = false; 32cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool g_traceGovernorLoad = false; 33fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceWorkqueue = false; 34fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceOverwrite = false; 35cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic int g_traceBufferSizeKB = 2048; 367b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennisstatic bool g_compress = false; 37fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 38fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Global state */ 39fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceAborted = false; 40fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 41fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Sys file paths */ 42fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceClockPath = 43fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace_clock"; 44fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 45cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_traceBufferSizePath = 46cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis "/sys/kernel/debug/tracing/buffer_size_kb"; 47cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 48fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOverwriteEnablePath = 49fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/options/overwrite"; 50fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 51fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_schedSwitchEnablePath = 52fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/events/sched/sched_switch/enable"; 53fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 54cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_cpuFreqEnablePath = 55cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable"; 56cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 57cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_governorLoadEnablePath = 58cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable"; 59cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 60fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_workqueueEnablePath = 61fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/events/workqueue/enable"; 62fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 63fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOnPath = 64fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/tracing_on"; 65fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 66fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracePath = 67fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace"; 68fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 69fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceMarkerPath = 70fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace_marker"; 71fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 72fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Write a string to a file, returning true if the write was successful. 73fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisbool writeStr(const char* filename, const char* str) 74fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 75fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int fd = open(filename, O_WRONLY); 76fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (fd == -1) { 77fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", filename, 78fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 79fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 80fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 81fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 82fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 83fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ssize_t len = strlen(str); 84fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (write(fd, str, len) != len) { 85fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error writing to %s: %s (%d)\n", filename, 86fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 87fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = false; 88fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 89fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 90fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(fd); 91fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 92fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 93fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 94fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 95fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file. 96fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable) 97fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 98fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(filename, enable ? "1" : "0"); 99fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 100fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 101fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable overwriting of the kernel trace buffers. Disabling this 102fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// will cause tracing to stop once the trace buffers have filled up. 103fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTraceOverwriteEnable(bool enable) 104fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 105fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable); 106fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 107fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 108fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable tracing of the kernel scheduler switching. 109fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setSchedSwitchTracingEnable(bool enable) 110fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 111fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_schedSwitchEnablePath, enable); 112fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 113fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 114cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Enable or disable tracing of the CPU clock frequency. 115cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setCpuFrequencyTracingEnable(bool enable) 116cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{ 117cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis return setKernelOptionEnable(k_cpuFreqEnablePath, enable); 118cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 119cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 120cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Enable or disable tracing of the interactive CPU frequency governor's idea of 121cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// the CPU load. 122cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setGovernorLoadTracingEnable(bool enable) 123cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{ 124cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis return setKernelOptionEnable(k_governorLoadEnablePath, enable); 125cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 126cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 127fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable tracing of the kernel workqueues. 128fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setWorkqueueTracingEnabled(bool enable) 129fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 130fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_workqueueEnablePath, enable); 131fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 132fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 133fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable kernel tracing. 134fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTracingEnabled(bool enable) 135fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 136fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_tracingOnPath, enable); 137fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 138fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 139fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Clear the contents of the kernel trace. 140fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool clearTrace() 141fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 142fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = creat(k_tracePath, 0); 143fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 144fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath, 145fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 146fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 147fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 148fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 149fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 150fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 151fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return true; 152fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 153fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 154cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Set the size of the kernel's trace buffer in kilobytes. 155cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setTraceBufferSizeKB(int size) 156cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{ 157cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis char str[32] = "1"; 158cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis int len; 159cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis if (size < 1) { 160cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis size = 1; 161cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis } 162cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis snprintf(str, 32, "%d", size); 163cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis return writeStr(k_traceBufferSizePath, str); 164cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 165cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 166fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable the kernel's use of the global clock. Disabling the global 167fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// clock will result in the kernel using a per-CPU local clock. 168fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setGlobalClockEnable(bool enable) 169fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 170fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(k_traceClockPath, enable ? "global" : "local"); 171fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 172fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 173fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis// Check whether a file exists. 174fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennisstatic bool fileExists(const char* filename) { 175fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis return access(filename, F_OK) != -1; 176fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis} 177fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis 178fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable tracing in the kernel. 179fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool startTrace() 180fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 181fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 182fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 183fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Set up the tracing options. 184fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTraceOverwriteEnable(g_traceOverwrite); 185fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch); 186cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis ok &= setCpuFrequencyTracingEnable(g_traceCpuFrequency); 187fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis if (fileExists(k_governorLoadEnablePath) || g_traceGovernorLoad) { 188fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis ok &= setGovernorLoadTracingEnable(g_traceGovernorLoad); 189fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis } 190fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setWorkqueueTracingEnabled(g_traceWorkqueue); 191cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis ok &= setTraceBufferSizeKB(g_traceBufferSizeKB); 192fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setGlobalClockEnable(true); 193fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 194fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Enable tracing. 195fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTracingEnabled(true); 196fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 197fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (!ok) { 198fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error: unable to start trace\n"); 199fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 200fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 201fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 202fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 203fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 204fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Disable tracing in the kernel. 205fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void stopTrace() 206fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 207fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Disable tracing. 208fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTracingEnabled(false); 209fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 210fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Set the options back to their defaults. 211fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTraceOverwriteEnable(true); 212fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setSchedSwitchTracingEnable(false); 213cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis setCpuFrequencyTracingEnable(false); 214fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis if (fileExists(k_governorLoadEnablePath)) { 215fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis setGovernorLoadTracingEnable(false); 216fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis } 217fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setWorkqueueTracingEnabled(false); 218fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setGlobalClockEnable(false); 219cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 220cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // Note that we can't reset the trace buffer size here because that would 221cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // clear the trace before we've read it. 222fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 223fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 224fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Read the current kernel trace and write it to stdout. 225fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void dumpTrace() 226fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 227fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = open(k_tracePath, O_RDWR); 228fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 229fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath, 230fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 231fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return; 232fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 233fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 2347b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (g_compress) { 2357b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis z_stream zs; 2367b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis uint8_t *in, *out; 2377b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis int result, flush; 2387b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2397b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis bzero(&zs, sizeof(zs)); 2407b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = deflateInit(&zs, Z_DEFAULT_COMPRESSION); 2417b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_OK) { 2427b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error initializing zlib: %d\n", result); 2437b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis close(traceFD); 2447b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis return; 2457b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2467b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2477b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis const size_t bufSize = 64*1024; 2487b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis in = (uint8_t*)malloc(bufSize); 2497b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis out = (uint8_t*)malloc(bufSize); 2507b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis flush = Z_NO_FLUSH; 2517b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2527b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_out = out; 2537b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; 2547b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2557b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis do { 2567b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2577b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_in == 0) { 2587b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis // More input is needed. 2597b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = read(traceFD, in, bufSize); 2607b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result < 0) { 2617b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error reading trace: %s (%d)\n", 2627b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 2637b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = Z_STREAM_END; 2647b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 2657b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else if (result == 0) { 2667b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis flush = Z_FINISH; 2677b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else { 2687b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_in = in; 2697b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_in = result; 2707b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2717b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2727b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2737b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_out == 0) { 2747b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis // Need to write the output. 2757b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = write(STDOUT_FILENO, out, bufSize); 2767b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if ((size_t)result < bufSize) { 2777b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 2787b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 2797b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = Z_STREAM_END; // skip deflate error message 2807b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; // skip the final write 2817b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 2827b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2837b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_out = out; 2847b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; 2857b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2867b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2877b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } while ((result = deflate(&zs, flush)) == Z_OK); 2887b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2897b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_STREAM_END) { 2907b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error deflating trace: %s\n", zs.msg); 2917b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2927b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2937b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_out < bufSize) { 2947b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis size_t bytes = bufSize - zs.avail_out; 2957b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = write(STDOUT_FILENO, out, bytes); 2967b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if ((size_t)result < bytes) { 2977b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 2987b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 2997b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 3007b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 3017b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 3027b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = deflateEnd(&zs); 3037b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_OK) { 3047b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error cleaning up zlib: %d\n", result); 3057b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 3067b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 3077b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis free(in); 3087b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis free(out); 3097b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else { 3107b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis ssize_t sent = 0; 3117b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0); 3127b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (sent == -1) { 3137b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno), 3147b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis errno); 3157b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 316fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 317fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 318fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 319fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 320fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 321fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Print the command usage help to stderr. 322fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void showHelp(const char *cmd) 323fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 324fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "usage: %s [options]\n", cmd); 325fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "options include:\n" 326cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis " -b N use a trace buffer size of N KB\n" 327fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -c trace into a circular buffer\n" 328cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis " -f trace CPU frequency changes\n" 329cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis " -l trace CPU frequency governor load\n" 330fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -s trace the kernel scheduler switches\n" 331fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -t N trace for N seconds [defualt 5]\n" 3327b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis " -w trace the kernel workqueue\n" 3337b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis " -z compress the trace dump\n"); 334fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 335fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 336fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void handleSignal(int signo) { 337fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceAborted = true; 338fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 339fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 340fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void registerSigHandler() { 341fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct sigaction sa; 342fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigemptyset(&sa.sa_mask); 343fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_flags = 0; 344fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_handler = handleSignal; 345fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGHUP, &sa, NULL); 346fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGINT, &sa, NULL); 347fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGQUIT, &sa, NULL); 348fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGTERM, &sa, NULL); 349fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 350fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 351fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisint main(int argc, char **argv) 352fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 353fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (argc == 2 && 0 == strcmp(argv[1], "--help")) { 354fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 355fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(0); 356fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 357fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 358fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (getuid() != 0) { 359fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error: %s must be run as root.", argv[0]); 360cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis exit(1); 361fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 362fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 363fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis for (;;) { 364fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int ret; 365fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 3667b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis ret = getopt(argc, argv, "b:cflst:wz"); 367fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 368fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ret < 0) { 369fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 370fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 371fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 372fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis switch(ret) { 373cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis case 'b': 374cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis g_traceBufferSizeKB = atoi(optarg); 375cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis break; 376cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 377fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 'c': 378fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceOverwrite = true; 379fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 380fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 381cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis case 'l': 382cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis g_traceGovernorLoad = true; 383cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis break; 384cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 385cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis case 'f': 386cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis g_traceCpuFrequency = true; 387cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis break; 388cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 389fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 's': 390fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceSchedSwitch = true; 391fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 392fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 393fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 't': 394fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceDurationSeconds = atoi(optarg); 395fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 396fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 397fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 'w': 398fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceWorkqueue = true; 399fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 400fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 4017b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis case 'z': 4027b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis g_compress = true; 4037b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 4047b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 405fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis default: 406cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis fprintf(stderr, "\n"); 407fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 408fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(-1); 409fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 410fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 411fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 412fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 413fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis registerSigHandler(); 414fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 415fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = startTrace(); 416fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 417fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 418fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("capturing trace..."); 419fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 420fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 421fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // We clear the trace after starting it because tracing gets enabled for 422fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // each CPU individually in the kernel. Having the beginning of the trace 423fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // contain entries from only one CPU can cause "begin" entries without a 424fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // matching "end" entry to show up if a task gets migrated from one CPU to 425fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // another. 426fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = clearTrace(); 427fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 428fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 429fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Sleep to allow the trace to be captured. 430fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct timespec timeLeft; 431fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_sec = g_traceDurationSeconds; 432fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_nsec = 0; 433fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis do { 434fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (g_traceAborted) { 435fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 436fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 437fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR); 438fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 439fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 440fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 441fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Stop the trace and restore the default settings. 442fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis stopTrace(); 443fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 444fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 445fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (!g_traceAborted) { 446fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf(" done\nTRACE:\n"); 447fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 448fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis dumpTrace(); 449fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } else { 450fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("\ntrace aborted.\n"); 451fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 452fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 453fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis clearTrace(); 454fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } else { 455fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "unable to start tracing\n"); 456fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 457fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 458cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // Reset the trace buffer size to 1. 459cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis setTraceBufferSizeKB(1); 460cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 461fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return g_traceAborted ? 1 : 0; 462fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 463