atrace.cpp revision 3169533f1d11c4a7aa0cd6fa2aa04fc810db0de6
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; 323169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennisstatic bool g_traceCpuIdle = false; 33cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool g_traceGovernorLoad = false; 34fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceWorkqueue = false; 35fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceOverwrite = false; 36cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic int g_traceBufferSizeKB = 2048; 377b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennisstatic bool g_compress = false; 38fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 39fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Global state */ 40fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceAborted = false; 41fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 42fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Sys file paths */ 43fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceClockPath = 44fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace_clock"; 45fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 46cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_traceBufferSizePath = 47cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis "/sys/kernel/debug/tracing/buffer_size_kb"; 48cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 49fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOverwriteEnablePath = 50fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/options/overwrite"; 51fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 52fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_schedSwitchEnablePath = 53fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/events/sched/sched_switch/enable"; 54fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 55cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_cpuFreqEnablePath = 56cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable"; 57cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 583169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennisstatic const char* k_cpuIdleEnablePath = 593169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis "/sys/kernel/debug/tracing/events/power/cpu_idle/enable"; 603169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis 61cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_governorLoadEnablePath = 62cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable"; 63cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 64fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_workqueueEnablePath = 65fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/events/workqueue/enable"; 66fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 67fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOnPath = 68fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/tracing_on"; 69fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 70fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracePath = 71fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace"; 72fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 73fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceMarkerPath = 74fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace_marker"; 75fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 76fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Write a string to a file, returning true if the write was successful. 77fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisbool writeStr(const char* filename, const char* str) 78fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 79fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int fd = open(filename, O_WRONLY); 80fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (fd == -1) { 81fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", filename, 82fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 83fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 84fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 85fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 86fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 87fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ssize_t len = strlen(str); 88fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (write(fd, str, len) != len) { 89fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error writing to %s: %s (%d)\n", filename, 90fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 91fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = false; 92fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 93fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 94fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(fd); 95fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 96fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 97fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 98fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 99fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file. 100fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable) 101fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 102fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(filename, enable ? "1" : "0"); 103fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 104fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 105fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable overwriting of the kernel trace buffers. Disabling this 106fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// will cause tracing to stop once the trace buffers have filled up. 107fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTraceOverwriteEnable(bool enable) 108fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 109fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable); 110fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 111fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 112fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable tracing of the kernel scheduler switching. 113fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setSchedSwitchTracingEnable(bool enable) 114fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 115fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_schedSwitchEnablePath, enable); 116fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 117fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 118cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Enable or disable tracing of the CPU clock frequency. 119cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setCpuFrequencyTracingEnable(bool enable) 120cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{ 121cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis return setKernelOptionEnable(k_cpuFreqEnablePath, enable); 122cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 123cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 1243169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis// Enable or disable tracing of CPU idle events. 1253169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennisstatic bool setCpuIdleTracingEnable(bool enable) 1263169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis{ 1273169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis return setKernelOptionEnable(k_cpuIdleEnablePath, enable); 1283169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis} 1293169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis 130cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Enable or disable tracing of the interactive CPU frequency governor's idea of 131cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// the CPU load. 132cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setGovernorLoadTracingEnable(bool enable) 133cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{ 134cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis return setKernelOptionEnable(k_governorLoadEnablePath, enable); 135cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 136cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 137fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable tracing of the kernel workqueues. 138fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setWorkqueueTracingEnabled(bool enable) 139fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 140fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_workqueueEnablePath, enable); 141fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 142fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 143fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable kernel tracing. 144fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTracingEnabled(bool enable) 145fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 146fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_tracingOnPath, enable); 147fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 148fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 149fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Clear the contents of the kernel trace. 150fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool clearTrace() 151fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 152fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = creat(k_tracePath, 0); 153fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 154fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath, 155fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 156fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 157fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 158fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 159fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 160fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 161fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return true; 162fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 163fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 164cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Set the size of the kernel's trace buffer in kilobytes. 165cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setTraceBufferSizeKB(int size) 166cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{ 167cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis char str[32] = "1"; 168cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis int len; 169cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis if (size < 1) { 170cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis size = 1; 171cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis } 172cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis snprintf(str, 32, "%d", size); 173cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis return writeStr(k_traceBufferSizePath, str); 174cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 175cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 176fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable the kernel's use of the global clock. Disabling the global 177fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// clock will result in the kernel using a per-CPU local clock. 178fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setGlobalClockEnable(bool enable) 179fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 180fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(k_traceClockPath, enable ? "global" : "local"); 181fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 182fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 183fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis// Check whether a file exists. 184fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennisstatic bool fileExists(const char* filename) { 185fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis return access(filename, F_OK) != -1; 186fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis} 187fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis 188fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable tracing in the kernel. 189fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool startTrace() 190fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 191fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 192fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 193fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Set up the tracing options. 194fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTraceOverwriteEnable(g_traceOverwrite); 195fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch); 196cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis ok &= setCpuFrequencyTracingEnable(g_traceCpuFrequency); 1973169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis ok &= setCpuIdleTracingEnable(g_traceCpuIdle); 198fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis if (fileExists(k_governorLoadEnablePath) || g_traceGovernorLoad) { 199fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis ok &= setGovernorLoadTracingEnable(g_traceGovernorLoad); 200fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis } 201fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setWorkqueueTracingEnabled(g_traceWorkqueue); 202cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis ok &= setTraceBufferSizeKB(g_traceBufferSizeKB); 203fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setGlobalClockEnable(true); 204fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 205fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Enable tracing. 206fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTracingEnabled(true); 207fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 208fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (!ok) { 209fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error: unable to start trace\n"); 210fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 211fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 212fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 213fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 214fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 215fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Disable tracing in the kernel. 216fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void stopTrace() 217fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 218fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Disable tracing. 219fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTracingEnabled(false); 220fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 221fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Set the options back to their defaults. 222fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTraceOverwriteEnable(true); 223fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setSchedSwitchTracingEnable(false); 224cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis setCpuFrequencyTracingEnable(false); 225fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis if (fileExists(k_governorLoadEnablePath)) { 226fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis setGovernorLoadTracingEnable(false); 227fe312b98f747d7818ce865fb5b12b805f2ce9a9bJamie Gennis } 228fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setWorkqueueTracingEnabled(false); 229fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setGlobalClockEnable(false); 230cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 231cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // Note that we can't reset the trace buffer size here because that would 232cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // clear the trace before we've read it. 233fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 234fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 235fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Read the current kernel trace and write it to stdout. 236fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void dumpTrace() 237fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 238fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = open(k_tracePath, O_RDWR); 239fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 240fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath, 241fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 242fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return; 243fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 244fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 2457b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (g_compress) { 2467b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis z_stream zs; 2477b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis uint8_t *in, *out; 2487b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis int result, flush; 2497b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2507b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis bzero(&zs, sizeof(zs)); 2517b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = deflateInit(&zs, Z_DEFAULT_COMPRESSION); 2527b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_OK) { 2537b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error initializing zlib: %d\n", result); 2547b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis close(traceFD); 2557b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis return; 2567b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2577b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2587b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis const size_t bufSize = 64*1024; 2597b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis in = (uint8_t*)malloc(bufSize); 2607b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis out = (uint8_t*)malloc(bufSize); 2617b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis flush = Z_NO_FLUSH; 2627b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2637b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_out = out; 2647b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; 2657b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2667b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis do { 2677b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2687b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_in == 0) { 2697b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis // More input is needed. 2707b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = read(traceFD, in, bufSize); 2717b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result < 0) { 2727b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error reading trace: %s (%d)\n", 2737b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 2747b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = Z_STREAM_END; 2757b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 2767b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else if (result == 0) { 2777b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis flush = Z_FINISH; 2787b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else { 2797b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_in = in; 2807b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_in = result; 2817b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2827b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2837b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2847b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_out == 0) { 2857b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis // Need to write the output. 2867b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = write(STDOUT_FILENO, out, bufSize); 2877b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if ((size_t)result < bufSize) { 2887b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 2897b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 2907b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = Z_STREAM_END; // skip deflate error message 2917b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; // skip the final write 2927b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 2937b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2947b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_out = out; 2957b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; 2967b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 2977b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 2987b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } while ((result = deflate(&zs, flush)) == Z_OK); 2997b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 3007b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_STREAM_END) { 3017b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error deflating trace: %s\n", zs.msg); 3027b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 3037b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 3047b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_out < bufSize) { 3057b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis size_t bytes = bufSize - zs.avail_out; 3067b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = write(STDOUT_FILENO, out, bytes); 3077b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if ((size_t)result < bytes) { 3087b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 3097b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 3107b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 3117b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 3127b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 3137b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = deflateEnd(&zs); 3147b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_OK) { 3157b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error cleaning up zlib: %d\n", result); 3167b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 3177b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 3187b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis free(in); 3197b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis free(out); 3207b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else { 3217b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis ssize_t sent = 0; 3227b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0); 3237b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (sent == -1) { 3247b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno), 3257b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis errno); 3267b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 327fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 328fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 329fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 330fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 331fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 332fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Print the command usage help to stderr. 333fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void showHelp(const char *cmd) 334fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 335fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "usage: %s [options]\n", cmd); 336fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "options include:\n" 337cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis " -b N use a trace buffer size of N KB\n" 338fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -c trace into a circular buffer\n" 339cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis " -f trace CPU frequency changes\n" 340cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis " -l trace CPU frequency governor load\n" 341fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -s trace the kernel scheduler switches\n" 342fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -t N trace for N seconds [defualt 5]\n" 3437b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis " -w trace the kernel workqueue\n" 3447b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis " -z compress the trace dump\n"); 345fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 346fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 347fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void handleSignal(int signo) { 348fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceAborted = true; 349fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 350fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 351fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void registerSigHandler() { 352fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct sigaction sa; 353fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigemptyset(&sa.sa_mask); 354fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_flags = 0; 355fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_handler = handleSignal; 356fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGHUP, &sa, NULL); 357fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGINT, &sa, NULL); 358fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGQUIT, &sa, NULL); 359fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGTERM, &sa, NULL); 360fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 361fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 362fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisint main(int argc, char **argv) 363fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 364fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (argc == 2 && 0 == strcmp(argv[1], "--help")) { 365fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 366fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(0); 367fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 368fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 369fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (getuid() != 0) { 370fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error: %s must be run as root.", argv[0]); 371cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis exit(1); 372fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 373fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 374fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis for (;;) { 375fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int ret; 376fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 3773169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis ret = getopt(argc, argv, "b:ciflst:wz"); 378fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 379fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ret < 0) { 380fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 381fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 382fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 383fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis switch(ret) { 384cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis case 'b': 385cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis g_traceBufferSizeKB = atoi(optarg); 386cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis break; 387cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 388fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 'c': 389fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceOverwrite = true; 390fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 391fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 3923169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis case 'i': 3933169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis g_traceCpuIdle = true; 3943169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis break; 3953169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis 396cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis case 'l': 397cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis g_traceGovernorLoad = true; 398cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis break; 399cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 400cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis case 'f': 401cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis g_traceCpuFrequency = true; 402cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis break; 403cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 404fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 's': 405fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceSchedSwitch = true; 406fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 407fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 408fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 't': 409fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceDurationSeconds = atoi(optarg); 410fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 411fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 412fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 'w': 413fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceWorkqueue = true; 414fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 415fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 4167b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis case 'z': 4177b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis g_compress = true; 4187b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 4197b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 420fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis default: 421cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis fprintf(stderr, "\n"); 422fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 423fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(-1); 424fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 425fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 426fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 427fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 428fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis registerSigHandler(); 429fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 430fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = startTrace(); 431fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 432fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 433fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("capturing trace..."); 434fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 435fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 436fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // We clear the trace after starting it because tracing gets enabled for 437fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // each CPU individually in the kernel. Having the beginning of the trace 438fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // contain entries from only one CPU can cause "begin" entries without a 439fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // matching "end" entry to show up if a task gets migrated from one CPU to 440fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // another. 441fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = clearTrace(); 442fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 443fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 444fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Sleep to allow the trace to be captured. 445fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct timespec timeLeft; 446fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_sec = g_traceDurationSeconds; 447fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_nsec = 0; 448fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis do { 449fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (g_traceAborted) { 450fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 451fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 452fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR); 453fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 454fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 455fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 456fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Stop the trace and restore the default settings. 457fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis stopTrace(); 458fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 459fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 460fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (!g_traceAborted) { 461fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf(" done\nTRACE:\n"); 462fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 463fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis dumpTrace(); 464fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } else { 465fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("\ntrace aborted.\n"); 466fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 467fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 468fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis clearTrace(); 469fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } else { 470fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "unable to start tracing\n"); 471fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 472fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 473cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // Reset the trace buffer size to 1. 474cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis setTraceBufferSizeKB(1); 475cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 476fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return g_traceAborted ? 1 : 0; 477fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 478