atrace.c revision 6b995818535af84c4a6829af7733684861f20144
16b995818535af84c4a6829af7733684861f20144Jamie Gennis/* 26b995818535af84c4a6829af7733684861f20144Jamie Gennis * Copyright (C) 2012 The Android Open Source Project 36b995818535af84c4a6829af7733684861f20144Jamie Gennis * 46b995818535af84c4a6829af7733684861f20144Jamie Gennis * Licensed under the Apache License, Version 2.0 (the "License"); 56b995818535af84c4a6829af7733684861f20144Jamie Gennis * you may not use this file except in compliance with the License. 66b995818535af84c4a6829af7733684861f20144Jamie Gennis * You may obtain a copy of the License at 76b995818535af84c4a6829af7733684861f20144Jamie Gennis * 86b995818535af84c4a6829af7733684861f20144Jamie Gennis * http://www.apache.org/licenses/LICENSE-2.0 96b995818535af84c4a6829af7733684861f20144Jamie Gennis * 106b995818535af84c4a6829af7733684861f20144Jamie Gennis * Unless required by applicable law or agreed to in writing, software 116b995818535af84c4a6829af7733684861f20144Jamie Gennis * distributed under the License is distributed on an "AS IS" BASIS, 126b995818535af84c4a6829af7733684861f20144Jamie Gennis * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136b995818535af84c4a6829af7733684861f20144Jamie Gennis * See the License for the specific language governing permissions and 146b995818535af84c4a6829af7733684861f20144Jamie Gennis * limitations under the License. 156b995818535af84c4a6829af7733684861f20144Jamie Gennis */ 166b995818535af84c4a6829af7733684861f20144Jamie Gennis 176b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <errno.h> 186b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <fcntl.h> 196b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <signal.h> 206b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <stdarg.h> 216b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <stdbool.h> 226b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <stdio.h> 236b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <stdlib.h> 246b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <sys/sendfile.h> 256b995818535af84c4a6829af7733684861f20144Jamie Gennis#include <time.h> 266b995818535af84c4a6829af7733684861f20144Jamie Gennis 276b995818535af84c4a6829af7733684861f20144Jamie Gennis/* Command line options */ 286b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic int g_traceDurationSeconds = 5; 296b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceSchedSwitch = false; 306b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceWorkqueue = false; 316b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceOverwrite = false; 326b995818535af84c4a6829af7733684861f20144Jamie Gennis 336b995818535af84c4a6829af7733684861f20144Jamie Gennis/* Global state */ 346b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceAborted = false; 356b995818535af84c4a6829af7733684861f20144Jamie Gennis 366b995818535af84c4a6829af7733684861f20144Jamie Gennis/* Sys file paths */ 376b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_traceClockPath = 386b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/trace_clock"; 396b995818535af84c4a6829af7733684861f20144Jamie Gennis 406b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_tracingOverwriteEnablePath = 416b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/options/overwrite"; 426b995818535af84c4a6829af7733684861f20144Jamie Gennis 436b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_schedSwitchEnablePath = 446b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/events/sched/sched_switch/enable"; 456b995818535af84c4a6829af7733684861f20144Jamie Gennis 466b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_workqueueEnablePath = 476b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/events/workqueue/enable"; 486b995818535af84c4a6829af7733684861f20144Jamie Gennis 496b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_tracingOnPath = 506b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/tracing_on"; 516b995818535af84c4a6829af7733684861f20144Jamie Gennis 526b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_tracePath = 536b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/trace"; 546b995818535af84c4a6829af7733684861f20144Jamie Gennis 556b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_traceMarkerPath = 566b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/trace_marker"; 576b995818535af84c4a6829af7733684861f20144Jamie Gennis 586b995818535af84c4a6829af7733684861f20144Jamie Gennis// Write a string to a file, returning true if the write was successful. 596b995818535af84c4a6829af7733684861f20144Jamie Gennisbool writeStr(const char* filename, const char* str) 606b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 616b995818535af84c4a6829af7733684861f20144Jamie Gennis int fd = open(filename, O_WRONLY); 626b995818535af84c4a6829af7733684861f20144Jamie Gennis if (fd == -1) { 636b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", filename, 646b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 656b995818535af84c4a6829af7733684861f20144Jamie Gennis return false; 666b995818535af84c4a6829af7733684861f20144Jamie Gennis } 676b995818535af84c4a6829af7733684861f20144Jamie Gennis 686b995818535af84c4a6829af7733684861f20144Jamie Gennis bool ok = true; 696b995818535af84c4a6829af7733684861f20144Jamie Gennis ssize_t len = strlen(str); 706b995818535af84c4a6829af7733684861f20144Jamie Gennis if (write(fd, str, len) != len) { 716b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error writing to %s: %s (%d)\n", filename, 726b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 736b995818535af84c4a6829af7733684861f20144Jamie Gennis ok = false; 746b995818535af84c4a6829af7733684861f20144Jamie Gennis } 756b995818535af84c4a6829af7733684861f20144Jamie Gennis 766b995818535af84c4a6829af7733684861f20144Jamie Gennis close(fd); 776b995818535af84c4a6829af7733684861f20144Jamie Gennis 786b995818535af84c4a6829af7733684861f20144Jamie Gennis return ok; 796b995818535af84c4a6829af7733684861f20144Jamie Gennis} 806b995818535af84c4a6829af7733684861f20144Jamie Gennis 816b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file. 826b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable) 836b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 846b995818535af84c4a6829af7733684861f20144Jamie Gennis return writeStr(filename, enable ? "1" : "0"); 856b995818535af84c4a6829af7733684861f20144Jamie Gennis} 866b995818535af84c4a6829af7733684861f20144Jamie Gennis 876b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable overwriting of the kernel trace buffers. Disabling this 886b995818535af84c4a6829af7733684861f20144Jamie Gennis// will cause tracing to stop once the trace buffers have filled up. 896b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setTraceOverwriteEnable(bool enable) 906b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 916b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable); 926b995818535af84c4a6829af7733684861f20144Jamie Gennis} 936b995818535af84c4a6829af7733684861f20144Jamie Gennis 946b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable tracing of the kernel scheduler switching. 956b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setSchedSwitchTracingEnable(bool enable) 966b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 976b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_schedSwitchEnablePath, enable); 986b995818535af84c4a6829af7733684861f20144Jamie Gennis} 996b995818535af84c4a6829af7733684861f20144Jamie Gennis 1006b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable tracing of the kernel workqueues. 1016b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setWorkqueueTracingEnabled(bool enable) 1026b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1036b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_workqueueEnablePath, enable); 1046b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1056b995818535af84c4a6829af7733684861f20144Jamie Gennis 1066b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable kernel tracing. 1076b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setTracingEnabled(bool enable) 1086b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1096b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_tracingOnPath, enable); 1106b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1116b995818535af84c4a6829af7733684861f20144Jamie Gennis 1126b995818535af84c4a6829af7733684861f20144Jamie Gennis// Clear the contents of the kernel trace. 1136b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool clearTrace() 1146b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1156b995818535af84c4a6829af7733684861f20144Jamie Gennis int traceFD = creat(k_tracePath, 0); 1166b995818535af84c4a6829af7733684861f20144Jamie Gennis if (traceFD == -1) { 1176b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath, 1186b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 1196b995818535af84c4a6829af7733684861f20144Jamie Gennis return false; 1206b995818535af84c4a6829af7733684861f20144Jamie Gennis } 1216b995818535af84c4a6829af7733684861f20144Jamie Gennis 1226b995818535af84c4a6829af7733684861f20144Jamie Gennis close(traceFD); 1236b995818535af84c4a6829af7733684861f20144Jamie Gennis 1246b995818535af84c4a6829af7733684861f20144Jamie Gennis return true; 1256b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1266b995818535af84c4a6829af7733684861f20144Jamie Gennis 1276b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable the kernel's use of the global clock. Disabling the global 1286b995818535af84c4a6829af7733684861f20144Jamie Gennis// clock will result in the kernel using a per-CPU local clock. 1296b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setGlobalClockEnable(bool enable) 1306b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1316b995818535af84c4a6829af7733684861f20144Jamie Gennis return writeStr(k_traceClockPath, enable ? "global" : "local"); 1326b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1336b995818535af84c4a6829af7733684861f20144Jamie Gennis 1346b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable tracing in the kernel. 1356b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool startTrace() 1366b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1376b995818535af84c4a6829af7733684861f20144Jamie Gennis bool ok = true; 1386b995818535af84c4a6829af7733684861f20144Jamie Gennis 1396b995818535af84c4a6829af7733684861f20144Jamie Gennis // Set up the tracing options. 1406b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setTraceOverwriteEnable(g_traceOverwrite); 1416b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch); 1426b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setWorkqueueTracingEnabled(g_traceWorkqueue); 1436b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setGlobalClockEnable(true); 1446b995818535af84c4a6829af7733684861f20144Jamie Gennis 1456b995818535af84c4a6829af7733684861f20144Jamie Gennis // Enable tracing. 1466b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setTracingEnabled(true); 1476b995818535af84c4a6829af7733684861f20144Jamie Gennis 1486b995818535af84c4a6829af7733684861f20144Jamie Gennis if (!ok) { 1496b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error: unable to start trace\n"); 1506b995818535af84c4a6829af7733684861f20144Jamie Gennis } 1516b995818535af84c4a6829af7733684861f20144Jamie Gennis 1526b995818535af84c4a6829af7733684861f20144Jamie Gennis return ok; 1536b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1546b995818535af84c4a6829af7733684861f20144Jamie Gennis 1556b995818535af84c4a6829af7733684861f20144Jamie Gennis// Disable tracing in the kernel. 1566b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void stopTrace() 1576b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1586b995818535af84c4a6829af7733684861f20144Jamie Gennis // Disable tracing. 1596b995818535af84c4a6829af7733684861f20144Jamie Gennis setTracingEnabled(false); 1606b995818535af84c4a6829af7733684861f20144Jamie Gennis 1616b995818535af84c4a6829af7733684861f20144Jamie Gennis // Set the options back to their defaults. 1626b995818535af84c4a6829af7733684861f20144Jamie Gennis setTraceOverwriteEnable(true); 1636b995818535af84c4a6829af7733684861f20144Jamie Gennis setSchedSwitchTracingEnable(false); 1646b995818535af84c4a6829af7733684861f20144Jamie Gennis setWorkqueueTracingEnabled(false); 1656b995818535af84c4a6829af7733684861f20144Jamie Gennis setGlobalClockEnable(false); 1666b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1676b995818535af84c4a6829af7733684861f20144Jamie Gennis 1686b995818535af84c4a6829af7733684861f20144Jamie Gennis// Read the current kernel trace and write it to stdout. 1696b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void dumpTrace() 1706b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1716b995818535af84c4a6829af7733684861f20144Jamie Gennis int traceFD = open(k_tracePath, O_RDWR); 1726b995818535af84c4a6829af7733684861f20144Jamie Gennis if (traceFD == -1) { 1736b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath, 1746b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 1756b995818535af84c4a6829af7733684861f20144Jamie Gennis return; 1766b995818535af84c4a6829af7733684861f20144Jamie Gennis } 1776b995818535af84c4a6829af7733684861f20144Jamie Gennis 1786b995818535af84c4a6829af7733684861f20144Jamie Gennis ssize_t sent = 0; 1796b995818535af84c4a6829af7733684861f20144Jamie Gennis while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0); 1806b995818535af84c4a6829af7733684861f20144Jamie Gennis if (sent == -1) { 1816b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno), 1826b995818535af84c4a6829af7733684861f20144Jamie Gennis errno); 1836b995818535af84c4a6829af7733684861f20144Jamie Gennis } 1846b995818535af84c4a6829af7733684861f20144Jamie Gennis 1856b995818535af84c4a6829af7733684861f20144Jamie Gennis close(traceFD); 1866b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1876b995818535af84c4a6829af7733684861f20144Jamie Gennis 1886b995818535af84c4a6829af7733684861f20144Jamie Gennis// Print the command usage help to stderr. 1896b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void showHelp(const char *cmd) 1906b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1916b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "usage: %s [options]\n", cmd); 1926b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "options include:\n" 1936b995818535af84c4a6829af7733684861f20144Jamie Gennis " -c trace into a circular buffer\n" 1946b995818535af84c4a6829af7733684861f20144Jamie Gennis " -s trace the kernel scheduler switches\n" 1956b995818535af84c4a6829af7733684861f20144Jamie Gennis " -t N trace for N seconds [defualt 5]\n" 1966b995818535af84c4a6829af7733684861f20144Jamie Gennis " -w trace the kernel workqueue\n"); 1976b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1986b995818535af84c4a6829af7733684861f20144Jamie Gennis 1996b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void handleSignal(int signo) { 2006b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceAborted = true; 2016b995818535af84c4a6829af7733684861f20144Jamie Gennis} 2026b995818535af84c4a6829af7733684861f20144Jamie Gennis 2036b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void registerSigHandler() { 2046b995818535af84c4a6829af7733684861f20144Jamie Gennis struct sigaction sa; 2056b995818535af84c4a6829af7733684861f20144Jamie Gennis sigemptyset(&sa.sa_mask); 2066b995818535af84c4a6829af7733684861f20144Jamie Gennis sa.sa_flags = 0; 2076b995818535af84c4a6829af7733684861f20144Jamie Gennis sa.sa_handler = handleSignal; 2086b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGHUP, &sa, NULL); 2096b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGINT, &sa, NULL); 2106b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGQUIT, &sa, NULL); 2116b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGTERM, &sa, NULL); 2126b995818535af84c4a6829af7733684861f20144Jamie Gennis} 2136b995818535af84c4a6829af7733684861f20144Jamie Gennis 2146b995818535af84c4a6829af7733684861f20144Jamie Gennisint main(int argc, char **argv) 2156b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 2166b995818535af84c4a6829af7733684861f20144Jamie Gennis if (argc == 2 && 0 == strcmp(argv[1], "--help")) { 2176b995818535af84c4a6829af7733684861f20144Jamie Gennis showHelp(argv[0]); 2186b995818535af84c4a6829af7733684861f20144Jamie Gennis exit(0); 2196b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2206b995818535af84c4a6829af7733684861f20144Jamie Gennis 2216b995818535af84c4a6829af7733684861f20144Jamie Gennis if (getuid() != 0) { 2226b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error: %s must be run as root.", argv[0]); 2236b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2246b995818535af84c4a6829af7733684861f20144Jamie Gennis 2256b995818535af84c4a6829af7733684861f20144Jamie Gennis for (;;) { 2266b995818535af84c4a6829af7733684861f20144Jamie Gennis int ret; 2276b995818535af84c4a6829af7733684861f20144Jamie Gennis 2286b995818535af84c4a6829af7733684861f20144Jamie Gennis ret = getopt(argc, argv, "cst:w"); 2296b995818535af84c4a6829af7733684861f20144Jamie Gennis 2306b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ret < 0) { 2316b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 2326b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2336b995818535af84c4a6829af7733684861f20144Jamie Gennis 2346b995818535af84c4a6829af7733684861f20144Jamie Gennis switch(ret) { 2356b995818535af84c4a6829af7733684861f20144Jamie Gennis case 'c': 2366b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceOverwrite = true; 2376b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 2386b995818535af84c4a6829af7733684861f20144Jamie Gennis 2396b995818535af84c4a6829af7733684861f20144Jamie Gennis case 's': 2406b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceSchedSwitch = true; 2416b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 2426b995818535af84c4a6829af7733684861f20144Jamie Gennis 2436b995818535af84c4a6829af7733684861f20144Jamie Gennis case 't': 2446b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceDurationSeconds = atoi(optarg); 2456b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 2466b995818535af84c4a6829af7733684861f20144Jamie Gennis 2476b995818535af84c4a6829af7733684861f20144Jamie Gennis case 'w': 2486b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceWorkqueue = true; 2496b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 2506b995818535af84c4a6829af7733684861f20144Jamie Gennis 2516b995818535af84c4a6829af7733684861f20144Jamie Gennis default: 2526b995818535af84c4a6829af7733684861f20144Jamie Gennis showHelp(argv[0]); 2536b995818535af84c4a6829af7733684861f20144Jamie Gennis exit(-1); 2546b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 2556b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2566b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2576b995818535af84c4a6829af7733684861f20144Jamie Gennis 2586b995818535af84c4a6829af7733684861f20144Jamie Gennis registerSigHandler(); 2596b995818535af84c4a6829af7733684861f20144Jamie Gennis 2606b995818535af84c4a6829af7733684861f20144Jamie Gennis bool ok = startTrace(); 2616b995818535af84c4a6829af7733684861f20144Jamie Gennis 2626b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ok) { 2636b995818535af84c4a6829af7733684861f20144Jamie Gennis printf("capturing trace..."); 2646b995818535af84c4a6829af7733684861f20144Jamie Gennis fflush(stdout); 2656b995818535af84c4a6829af7733684861f20144Jamie Gennis 2666b995818535af84c4a6829af7733684861f20144Jamie Gennis // We clear the trace after starting it because tracing gets enabled for 2676b995818535af84c4a6829af7733684861f20144Jamie Gennis // each CPU individually in the kernel. Having the beginning of the trace 2686b995818535af84c4a6829af7733684861f20144Jamie Gennis // contain entries from only one CPU can cause "begin" entries without a 2696b995818535af84c4a6829af7733684861f20144Jamie Gennis // matching "end" entry to show up if a task gets migrated from one CPU to 2706b995818535af84c4a6829af7733684861f20144Jamie Gennis // another. 2716b995818535af84c4a6829af7733684861f20144Jamie Gennis ok = clearTrace(); 2726b995818535af84c4a6829af7733684861f20144Jamie Gennis 2736b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ok) { 2746b995818535af84c4a6829af7733684861f20144Jamie Gennis // Sleep to allow the trace to be captured. 2756b995818535af84c4a6829af7733684861f20144Jamie Gennis struct timespec timeLeft; 2766b995818535af84c4a6829af7733684861f20144Jamie Gennis timeLeft.tv_sec = g_traceDurationSeconds; 2776b995818535af84c4a6829af7733684861f20144Jamie Gennis timeLeft.tv_nsec = 0; 2786b995818535af84c4a6829af7733684861f20144Jamie Gennis do { 2796b995818535af84c4a6829af7733684861f20144Jamie Gennis if (g_traceAborted) { 2806b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 2816b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2826b995818535af84c4a6829af7733684861f20144Jamie Gennis } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR); 2836b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2846b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2856b995818535af84c4a6829af7733684861f20144Jamie Gennis 2866b995818535af84c4a6829af7733684861f20144Jamie Gennis // Stop the trace and restore the default settings. 2876b995818535af84c4a6829af7733684861f20144Jamie Gennis stopTrace(); 2886b995818535af84c4a6829af7733684861f20144Jamie Gennis 2896b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ok) { 2906b995818535af84c4a6829af7733684861f20144Jamie Gennis if (!g_traceAborted) { 2916b995818535af84c4a6829af7733684861f20144Jamie Gennis printf(" done\nTRACE:\n"); 2926b995818535af84c4a6829af7733684861f20144Jamie Gennis fflush(stdout); 2936b995818535af84c4a6829af7733684861f20144Jamie Gennis dumpTrace(); 2946b995818535af84c4a6829af7733684861f20144Jamie Gennis } else { 2956b995818535af84c4a6829af7733684861f20144Jamie Gennis printf("\ntrace aborted.\n"); 2966b995818535af84c4a6829af7733684861f20144Jamie Gennis fflush(stdout); 2976b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2986b995818535af84c4a6829af7733684861f20144Jamie Gennis clearTrace(); 2996b995818535af84c4a6829af7733684861f20144Jamie Gennis } else { 3006b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "unable to start tracing\n"); 3016b995818535af84c4a6829af7733684861f20144Jamie Gennis } 3026b995818535af84c4a6829af7733684861f20144Jamie Gennis 3036b995818535af84c4a6829af7733684861f20144Jamie Gennis return g_traceAborted ? 1 : 0; 3046b995818535af84c4a6829af7733684861f20144Jamie Gennis} 305