atrace.cpp revision fb31ba69282e34df62005ec63afda2b8ec69533e
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> 26fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 27fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Command line options */ 28fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic int g_traceDurationSeconds = 5; 29fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceSchedSwitch = false; 30fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceWorkqueue = false; 31fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceOverwrite = false; 32fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 33fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Global state */ 34fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceAborted = false; 35fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 36fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Sys file paths */ 37fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceClockPath = 38fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace_clock"; 39fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 40fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOverwriteEnablePath = 41fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/options/overwrite"; 42fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 43fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_schedSwitchEnablePath = 44fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/events/sched/sched_switch/enable"; 45fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 46fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_workqueueEnablePath = 47fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/events/workqueue/enable"; 48fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 49fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOnPath = 50fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/tracing_on"; 51fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 52fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracePath = 53fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace"; 54fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 55fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceMarkerPath = 56fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace_marker"; 57fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 58fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Write a string to a file, returning true if the write was successful. 59fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisbool writeStr(const char* filename, const char* str) 60fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 61fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int fd = open(filename, O_WRONLY); 62fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (fd == -1) { 63fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", filename, 64fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 65fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 66fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 67fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 68fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 69fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ssize_t len = strlen(str); 70fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (write(fd, str, len) != len) { 71fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error writing to %s: %s (%d)\n", filename, 72fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 73fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = false; 74fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 75fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 76fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(fd); 77fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 78fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 79fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 80fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 81fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file. 82fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable) 83fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 84fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(filename, enable ? "1" : "0"); 85fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 86fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 87fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable overwriting of the kernel trace buffers. Disabling this 88fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// will cause tracing to stop once the trace buffers have filled up. 89fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTraceOverwriteEnable(bool enable) 90fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 91fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable); 92fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 93fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 94fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable tracing of the kernel scheduler switching. 95fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setSchedSwitchTracingEnable(bool enable) 96fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 97fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_schedSwitchEnablePath, enable); 98fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 99fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 100fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable tracing of the kernel workqueues. 101fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setWorkqueueTracingEnabled(bool enable) 102fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 103fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_workqueueEnablePath, enable); 104fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 105fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 106fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable kernel tracing. 107fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTracingEnabled(bool enable) 108fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 109fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_tracingOnPath, enable); 110fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 111fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 112fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Clear the contents of the kernel trace. 113fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool clearTrace() 114fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 115fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = creat(k_tracePath, 0); 116fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 117fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath, 118fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 119fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 120fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 121fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 122fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 123fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 124fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return true; 125fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 126fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 127fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable the kernel's use of the global clock. Disabling the global 128fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// clock will result in the kernel using a per-CPU local clock. 129fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setGlobalClockEnable(bool enable) 130fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 131fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(k_traceClockPath, enable ? "global" : "local"); 132fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 133fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 134fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable tracing in the kernel. 135fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool startTrace() 136fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 137fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 138fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 139fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Set up the tracing options. 140fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTraceOverwriteEnable(g_traceOverwrite); 141fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch); 142fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setWorkqueueTracingEnabled(g_traceWorkqueue); 143fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setGlobalClockEnable(true); 144fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 145fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Enable tracing. 146fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTracingEnabled(true); 147fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 148fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (!ok) { 149fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error: unable to start trace\n"); 150fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 151fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 152fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 153fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 154fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 155fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Disable tracing in the kernel. 156fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void stopTrace() 157fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 158fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Disable tracing. 159fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTracingEnabled(false); 160fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 161fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Set the options back to their defaults. 162fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTraceOverwriteEnable(true); 163fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setSchedSwitchTracingEnable(false); 164fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setWorkqueueTracingEnabled(false); 165fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setGlobalClockEnable(false); 166fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 167fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 168fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Read the current kernel trace and write it to stdout. 169fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void dumpTrace() 170fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 171fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = open(k_tracePath, O_RDWR); 172fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 173fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath, 174fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 175fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return; 176fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 177fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 178fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ssize_t sent = 0; 179fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0); 180fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (sent == -1) { 181fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno), 182fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis errno); 183fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 184fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 185fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 186fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 187fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 188fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Print the command usage help to stderr. 189fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void showHelp(const char *cmd) 190fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 191fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "usage: %s [options]\n", cmd); 192fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "options include:\n" 193fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -c trace into a circular buffer\n" 194fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -s trace the kernel scheduler switches\n" 195fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -t N trace for N seconds [defualt 5]\n" 196fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis " -w trace the kernel workqueue\n"); 197fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 198fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 199fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void handleSignal(int signo) { 200fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceAborted = true; 201fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 202fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 203fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void registerSigHandler() { 204fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct sigaction sa; 205fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigemptyset(&sa.sa_mask); 206fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_flags = 0; 207fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_handler = handleSignal; 208fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGHUP, &sa, NULL); 209fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGINT, &sa, NULL); 210fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGQUIT, &sa, NULL); 211fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGTERM, &sa, NULL); 212fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 213fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 214fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisint main(int argc, char **argv) 215fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 216fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (argc == 2 && 0 == strcmp(argv[1], "--help")) { 217fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 218fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(0); 219fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 220fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 221fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (getuid() != 0) { 222fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error: %s must be run as root.", argv[0]); 223fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 224fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 225fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis for (;;) { 226fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int ret; 227fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 228fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ret = getopt(argc, argv, "cst:w"); 229fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 230fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ret < 0) { 231fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 232fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 233fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 234fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis switch(ret) { 235fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 'c': 236fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceOverwrite = true; 237fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 238fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 239fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 's': 240fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceSchedSwitch = true; 241fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 242fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 243fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 't': 244fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceDurationSeconds = atoi(optarg); 245fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 246fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 247fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 'w': 248fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceWorkqueue = true; 249fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 250fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 251fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis default: 252fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 253fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(-1); 254fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 255fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 256fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 257fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 258fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis registerSigHandler(); 259fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 260fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = startTrace(); 261fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 262fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 263fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("capturing trace..."); 264fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 265fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 266fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // We clear the trace after starting it because tracing gets enabled for 267fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // each CPU individually in the kernel. Having the beginning of the trace 268fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // contain entries from only one CPU can cause "begin" entries without a 269fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // matching "end" entry to show up if a task gets migrated from one CPU to 270fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // another. 271fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = clearTrace(); 272fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 273fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 274fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Sleep to allow the trace to be captured. 275fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct timespec timeLeft; 276fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_sec = g_traceDurationSeconds; 277fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_nsec = 0; 278fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis do { 279fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (g_traceAborted) { 280fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 281fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 282fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR); 283fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 284fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 285fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 286fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Stop the trace and restore the default settings. 287fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis stopTrace(); 288fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 289fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ok) { 290fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (!g_traceAborted) { 291fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf(" done\nTRACE:\n"); 292fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 293fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis dumpTrace(); 294fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } else { 295fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("\ntrace aborted.\n"); 296fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 297fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 298fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis clearTrace(); 299fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } else { 300fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "unable to start tracing\n"); 301fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 302fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 303fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return g_traceAborted ? 1 : 0; 304fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 305