atrace.c revision 83fdbb05c39b030ef1e5b3a7db79c617114c20f4
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> 26eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis#include <zlib.h> 276b995818535af84c4a6829af7733684861f20144Jamie Gennis 2883fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) 2983fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown 306b995818535af84c4a6829af7733684861f20144Jamie Gennis/* Command line options */ 316b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic int g_traceDurationSeconds = 5; 326b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceSchedSwitch = false; 33bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic bool g_traceCpuFrequency = false; 34585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennisstatic bool g_traceCpuIdle = false; 3583fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brownstatic bool g_traceDisk = false; 36bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic bool g_traceGovernorLoad = false; 376b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceWorkqueue = false; 386b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceOverwrite = false; 39bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic int g_traceBufferSizeKB = 2048; 40eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennisstatic bool g_compress = false; 416b995818535af84c4a6829af7733684861f20144Jamie Gennis 426b995818535af84c4a6829af7733684861f20144Jamie Gennis/* Global state */ 436b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool g_traceAborted = false; 446b995818535af84c4a6829af7733684861f20144Jamie Gennis 456b995818535af84c4a6829af7733684861f20144Jamie Gennis/* Sys file paths */ 466b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_traceClockPath = 476b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/trace_clock"; 486b995818535af84c4a6829af7733684861f20144Jamie Gennis 49bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic const char* k_traceBufferSizePath = 50bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis "/sys/kernel/debug/tracing/buffer_size_kb"; 51bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 526b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_tracingOverwriteEnablePath = 536b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/options/overwrite"; 546b995818535af84c4a6829af7733684861f20144Jamie Gennis 556b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_schedSwitchEnablePath = 566b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/events/sched/sched_switch/enable"; 576b995818535af84c4a6829af7733684861f20144Jamie Gennis 58bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic const char* k_cpuFreqEnablePath = 59bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable"; 60bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 61585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennisstatic const char* k_cpuIdleEnablePath = 62585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis "/sys/kernel/debug/tracing/events/power/cpu_idle/enable"; 63585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis 64bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic const char* k_governorLoadEnablePath = 65bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable"; 66bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 676b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_workqueueEnablePath = 686b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/events/workqueue/enable"; 696b995818535af84c4a6829af7733684861f20144Jamie Gennis 7083fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brownstatic const char* k_diskEnablePaths[] = { 7183fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable", 7283fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable", 7383fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable", 7483fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable", 7583fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown}; 7683fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown 776b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_tracingOnPath = 786b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/tracing_on"; 796b995818535af84c4a6829af7733684861f20144Jamie Gennis 806b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_tracePath = 816b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/trace"; 826b995818535af84c4a6829af7733684861f20144Jamie Gennis 836b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic const char* k_traceMarkerPath = 846b995818535af84c4a6829af7733684861f20144Jamie Gennis "/sys/kernel/debug/tracing/trace_marker"; 856b995818535af84c4a6829af7733684861f20144Jamie Gennis 866b995818535af84c4a6829af7733684861f20144Jamie Gennis// Write a string to a file, returning true if the write was successful. 876b995818535af84c4a6829af7733684861f20144Jamie Gennisbool writeStr(const char* filename, const char* str) 886b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 896b995818535af84c4a6829af7733684861f20144Jamie Gennis int fd = open(filename, O_WRONLY); 906b995818535af84c4a6829af7733684861f20144Jamie Gennis if (fd == -1) { 916b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", filename, 926b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 936b995818535af84c4a6829af7733684861f20144Jamie Gennis return false; 946b995818535af84c4a6829af7733684861f20144Jamie Gennis } 956b995818535af84c4a6829af7733684861f20144Jamie Gennis 966b995818535af84c4a6829af7733684861f20144Jamie Gennis bool ok = true; 976b995818535af84c4a6829af7733684861f20144Jamie Gennis ssize_t len = strlen(str); 986b995818535af84c4a6829af7733684861f20144Jamie Gennis if (write(fd, str, len) != len) { 996b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error writing to %s: %s (%d)\n", filename, 1006b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 1016b995818535af84c4a6829af7733684861f20144Jamie Gennis ok = false; 1026b995818535af84c4a6829af7733684861f20144Jamie Gennis } 1036b995818535af84c4a6829af7733684861f20144Jamie Gennis 1046b995818535af84c4a6829af7733684861f20144Jamie Gennis close(fd); 1056b995818535af84c4a6829af7733684861f20144Jamie Gennis 1066b995818535af84c4a6829af7733684861f20144Jamie Gennis return ok; 1076b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1086b995818535af84c4a6829af7733684861f20144Jamie Gennis 1096b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file. 1106b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable) 1116b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1126b995818535af84c4a6829af7733684861f20144Jamie Gennis return writeStr(filename, enable ? "1" : "0"); 1136b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1146b995818535af84c4a6829af7733684861f20144Jamie Gennis 11583fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown// Enable or disable a collection of kernel options by writing a "1" or a "0" into each /sys file. 11683fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brownstatic bool setMultipleKernelOptionsEnable(const char** filenames, size_t count, bool enable) 11783fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown{ 11883fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown bool result = true; 11983fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown for (size_t i = 0; i < count; i++) { 12083fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown result &= setKernelOptionEnable(filenames[i], enable); 12183fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown } 12283fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown return result; 12383fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown} 12483fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown 1256b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable overwriting of the kernel trace buffers. Disabling this 1266b995818535af84c4a6829af7733684861f20144Jamie Gennis// will cause tracing to stop once the trace buffers have filled up. 1276b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setTraceOverwriteEnable(bool enable) 1286b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1296b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable); 1306b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1316b995818535af84c4a6829af7733684861f20144Jamie Gennis 1326b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable tracing of the kernel scheduler switching. 1336b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setSchedSwitchTracingEnable(bool enable) 1346b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1356b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_schedSwitchEnablePath, enable); 1366b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1376b995818535af84c4a6829af7733684861f20144Jamie Gennis 138bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis// Enable or disable tracing of the CPU clock frequency. 139bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic bool setCpuFrequencyTracingEnable(bool enable) 140bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis{ 141bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis return setKernelOptionEnable(k_cpuFreqEnablePath, enable); 142bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis} 143bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 144585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis// Enable or disable tracing of CPU idle events. 145585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennisstatic bool setCpuIdleTracingEnable(bool enable) 146585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis{ 147585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis return setKernelOptionEnable(k_cpuIdleEnablePath, enable); 148585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis} 149585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis 150bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis// Enable or disable tracing of the interactive CPU frequency governor's idea of 151bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis// the CPU load. 152bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic bool setGovernorLoadTracingEnable(bool enable) 153bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis{ 154bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis return setKernelOptionEnable(k_governorLoadEnablePath, enable); 155bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis} 156bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 1576b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable tracing of the kernel workqueues. 1586b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setWorkqueueTracingEnabled(bool enable) 1596b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1606b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_workqueueEnablePath, enable); 1616b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1626b995818535af84c4a6829af7733684861f20144Jamie Gennis 16383fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown// Enable or disable tracing of disk I/O. 16483fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brownstatic bool setDiskTracingEnabled(bool enable) 16583fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown{ 16683fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown return setMultipleKernelOptionsEnable(k_diskEnablePaths, NELEM(k_diskEnablePaths), enable); 16783fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown} 16883fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown 1696b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable kernel tracing. 1706b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setTracingEnabled(bool enable) 1716b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1726b995818535af84c4a6829af7733684861f20144Jamie Gennis return setKernelOptionEnable(k_tracingOnPath, enable); 1736b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1746b995818535af84c4a6829af7733684861f20144Jamie Gennis 1756b995818535af84c4a6829af7733684861f20144Jamie Gennis// Clear the contents of the kernel trace. 1766b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool clearTrace() 1776b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 1786b995818535af84c4a6829af7733684861f20144Jamie Gennis int traceFD = creat(k_tracePath, 0); 1796b995818535af84c4a6829af7733684861f20144Jamie Gennis if (traceFD == -1) { 1806b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath, 1816b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 1826b995818535af84c4a6829af7733684861f20144Jamie Gennis return false; 1836b995818535af84c4a6829af7733684861f20144Jamie Gennis } 1846b995818535af84c4a6829af7733684861f20144Jamie Gennis 1856b995818535af84c4a6829af7733684861f20144Jamie Gennis close(traceFD); 1866b995818535af84c4a6829af7733684861f20144Jamie Gennis 1876b995818535af84c4a6829af7733684861f20144Jamie Gennis return true; 1886b995818535af84c4a6829af7733684861f20144Jamie Gennis} 1896b995818535af84c4a6829af7733684861f20144Jamie Gennis 190bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis// Set the size of the kernel's trace buffer in kilobytes. 191bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennisstatic bool setTraceBufferSizeKB(int size) 192bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis{ 193bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis char str[32] = "1"; 194bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis int len; 195bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis if (size < 1) { 196bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis size = 1; 197bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis } 198bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis snprintf(str, 32, "%d", size); 199bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis return writeStr(k_traceBufferSizePath, str); 200bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis} 201bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 2026b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable or disable the kernel's use of the global clock. Disabling the global 2036b995818535af84c4a6829af7733684861f20144Jamie Gennis// clock will result in the kernel using a per-CPU local clock. 2046b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool setGlobalClockEnable(bool enable) 2056b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 2066b995818535af84c4a6829af7733684861f20144Jamie Gennis return writeStr(k_traceClockPath, enable ? "global" : "local"); 2076b995818535af84c4a6829af7733684861f20144Jamie Gennis} 2086b995818535af84c4a6829af7733684861f20144Jamie Gennis 209416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis// Check whether a file exists. 210416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennisstatic bool fileExists(const char* filename) { 211416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis return access(filename, F_OK) != -1; 212416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis} 213416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis 2146b995818535af84c4a6829af7733684861f20144Jamie Gennis// Enable tracing in the kernel. 2156b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic bool startTrace() 2166b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 2176b995818535af84c4a6829af7733684861f20144Jamie Gennis bool ok = true; 2186b995818535af84c4a6829af7733684861f20144Jamie Gennis 2196b995818535af84c4a6829af7733684861f20144Jamie Gennis // Set up the tracing options. 2206b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setTraceOverwriteEnable(g_traceOverwrite); 2216b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch); 222bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis ok &= setCpuFrequencyTracingEnable(g_traceCpuFrequency); 223585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis ok &= setCpuIdleTracingEnable(g_traceCpuIdle); 224416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis if (fileExists(k_governorLoadEnablePath) || g_traceGovernorLoad) { 225416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis ok &= setGovernorLoadTracingEnable(g_traceGovernorLoad); 226416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis } 2276b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setWorkqueueTracingEnabled(g_traceWorkqueue); 22883fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown ok &= setDiskTracingEnabled(g_traceDisk); 229bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis ok &= setTraceBufferSizeKB(g_traceBufferSizeKB); 2306b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setGlobalClockEnable(true); 2316b995818535af84c4a6829af7733684861f20144Jamie Gennis 2326b995818535af84c4a6829af7733684861f20144Jamie Gennis // Enable tracing. 2336b995818535af84c4a6829af7733684861f20144Jamie Gennis ok &= setTracingEnabled(true); 2346b995818535af84c4a6829af7733684861f20144Jamie Gennis 2356b995818535af84c4a6829af7733684861f20144Jamie Gennis if (!ok) { 2366b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error: unable to start trace\n"); 2376b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2386b995818535af84c4a6829af7733684861f20144Jamie Gennis 2396b995818535af84c4a6829af7733684861f20144Jamie Gennis return ok; 2406b995818535af84c4a6829af7733684861f20144Jamie Gennis} 2416b995818535af84c4a6829af7733684861f20144Jamie Gennis 2426b995818535af84c4a6829af7733684861f20144Jamie Gennis// Disable tracing in the kernel. 2436b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void stopTrace() 2446b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 2456b995818535af84c4a6829af7733684861f20144Jamie Gennis // Disable tracing. 2466b995818535af84c4a6829af7733684861f20144Jamie Gennis setTracingEnabled(false); 2476b995818535af84c4a6829af7733684861f20144Jamie Gennis 2486b995818535af84c4a6829af7733684861f20144Jamie Gennis // Set the options back to their defaults. 2496b995818535af84c4a6829af7733684861f20144Jamie Gennis setTraceOverwriteEnable(true); 2506b995818535af84c4a6829af7733684861f20144Jamie Gennis setSchedSwitchTracingEnable(false); 251bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis setCpuFrequencyTracingEnable(false); 252416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis if (fileExists(k_governorLoadEnablePath)) { 253416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis setGovernorLoadTracingEnable(false); 254416fd36c9f7097a11ea610522ef8297d2b82d27bJamie Gennis } 2556b995818535af84c4a6829af7733684861f20144Jamie Gennis setWorkqueueTracingEnabled(false); 2566b995818535af84c4a6829af7733684861f20144Jamie Gennis setGlobalClockEnable(false); 257bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 258bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis // Note that we can't reset the trace buffer size here because that would 259bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis // clear the trace before we've read it. 2606b995818535af84c4a6829af7733684861f20144Jamie Gennis} 2616b995818535af84c4a6829af7733684861f20144Jamie Gennis 2626b995818535af84c4a6829af7733684861f20144Jamie Gennis// Read the current kernel trace and write it to stdout. 2636b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void dumpTrace() 2646b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 2656b995818535af84c4a6829af7733684861f20144Jamie Gennis int traceFD = open(k_tracePath, O_RDWR); 2666b995818535af84c4a6829af7733684861f20144Jamie Gennis if (traceFD == -1) { 2676b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath, 2686b995818535af84c4a6829af7733684861f20144Jamie Gennis strerror(errno), errno); 2696b995818535af84c4a6829af7733684861f20144Jamie Gennis return; 2706b995818535af84c4a6829af7733684861f20144Jamie Gennis } 2716b995818535af84c4a6829af7733684861f20144Jamie Gennis 272eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (g_compress) { 273eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis z_stream zs; 274eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis uint8_t *in, *out; 275eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis int result, flush; 276eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 277eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis bzero(&zs, sizeof(zs)); 278eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis result = deflateInit(&zs, Z_DEFAULT_COMPRESSION); 279eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (result != Z_OK) { 280eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis fprintf(stderr, "error initializing zlib: %d\n", result); 281eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis close(traceFD); 282eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis return; 283eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 284eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 285eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis const size_t bufSize = 64*1024; 286eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis in = (uint8_t*)malloc(bufSize); 287eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis out = (uint8_t*)malloc(bufSize); 288eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis flush = Z_NO_FLUSH; 289eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 290eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis zs.next_out = out; 291eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis zs.avail_out = bufSize; 292eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 293eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis do { 294eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 295eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (zs.avail_in == 0) { 296eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis // More input is needed. 297eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis result = read(traceFD, in, bufSize); 298eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (result < 0) { 299eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis fprintf(stderr, "error reading trace: %s (%d)\n", 300eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis strerror(errno), errno); 301eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis result = Z_STREAM_END; 302eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis break; 303eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } else if (result == 0) { 304eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis flush = Z_FINISH; 305eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } else { 306eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis zs.next_in = in; 307eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis zs.avail_in = result; 308eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 309eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 310eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 311eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (zs.avail_out == 0) { 312eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis // Need to write the output. 313eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis result = write(STDOUT_FILENO, out, bufSize); 314eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if ((size_t)result < bufSize) { 315eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 316eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis strerror(errno), errno); 317eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis result = Z_STREAM_END; // skip deflate error message 318eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis zs.avail_out = bufSize; // skip the final write 319eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis break; 320eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 321eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis zs.next_out = out; 322eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis zs.avail_out = bufSize; 323eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 324eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 325eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } while ((result = deflate(&zs, flush)) == Z_OK); 326eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 327eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (result != Z_STREAM_END) { 328eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis fprintf(stderr, "error deflating trace: %s\n", zs.msg); 329eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 330eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 331eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (zs.avail_out < bufSize) { 332eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis size_t bytes = bufSize - zs.avail_out; 333eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis result = write(STDOUT_FILENO, out, bytes); 334eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if ((size_t)result < bytes) { 335eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 336eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis strerror(errno), errno); 337eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 338eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 339eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 340eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis result = deflateEnd(&zs); 341eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (result != Z_OK) { 342eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis fprintf(stderr, "error cleaning up zlib: %d\n", result); 343eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 344eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 345eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis free(in); 346eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis free(out); 347eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } else { 348eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis ssize_t sent = 0; 349eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0); 350eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis if (sent == -1) { 351eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno), 352eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis errno); 353eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis } 3546b995818535af84c4a6829af7733684861f20144Jamie Gennis } 3556b995818535af84c4a6829af7733684861f20144Jamie Gennis 3566b995818535af84c4a6829af7733684861f20144Jamie Gennis close(traceFD); 3576b995818535af84c4a6829af7733684861f20144Jamie Gennis} 3586b995818535af84c4a6829af7733684861f20144Jamie Gennis 3596b995818535af84c4a6829af7733684861f20144Jamie Gennis// Print the command usage help to stderr. 3606b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void showHelp(const char *cmd) 3616b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 3626b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "usage: %s [options]\n", cmd); 3636b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "options include:\n" 364bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis " -b N use a trace buffer size of N KB\n" 3656b995818535af84c4a6829af7733684861f20144Jamie Gennis " -c trace into a circular buffer\n" 36683fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown " -d trace disk I/O\n" 367bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis " -f trace CPU frequency changes\n" 368bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis " -l trace CPU frequency governor load\n" 3696b995818535af84c4a6829af7733684861f20144Jamie Gennis " -s trace the kernel scheduler switches\n" 3706b995818535af84c4a6829af7733684861f20144Jamie Gennis " -t N trace for N seconds [defualt 5]\n" 371eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis " -w trace the kernel workqueue\n" 372eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis " -z compress the trace dump\n"); 3736b995818535af84c4a6829af7733684861f20144Jamie Gennis} 3746b995818535af84c4a6829af7733684861f20144Jamie Gennis 3756b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void handleSignal(int signo) { 3766b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceAborted = true; 3776b995818535af84c4a6829af7733684861f20144Jamie Gennis} 3786b995818535af84c4a6829af7733684861f20144Jamie Gennis 3796b995818535af84c4a6829af7733684861f20144Jamie Gennisstatic void registerSigHandler() { 3806b995818535af84c4a6829af7733684861f20144Jamie Gennis struct sigaction sa; 3816b995818535af84c4a6829af7733684861f20144Jamie Gennis sigemptyset(&sa.sa_mask); 3826b995818535af84c4a6829af7733684861f20144Jamie Gennis sa.sa_flags = 0; 3836b995818535af84c4a6829af7733684861f20144Jamie Gennis sa.sa_handler = handleSignal; 3846b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGHUP, &sa, NULL); 3856b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGINT, &sa, NULL); 3866b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGQUIT, &sa, NULL); 3876b995818535af84c4a6829af7733684861f20144Jamie Gennis sigaction(SIGTERM, &sa, NULL); 3886b995818535af84c4a6829af7733684861f20144Jamie Gennis} 3896b995818535af84c4a6829af7733684861f20144Jamie Gennis 3906b995818535af84c4a6829af7733684861f20144Jamie Gennisint main(int argc, char **argv) 3916b995818535af84c4a6829af7733684861f20144Jamie Gennis{ 3926b995818535af84c4a6829af7733684861f20144Jamie Gennis if (argc == 2 && 0 == strcmp(argv[1], "--help")) { 3936b995818535af84c4a6829af7733684861f20144Jamie Gennis showHelp(argv[0]); 3946b995818535af84c4a6829af7733684861f20144Jamie Gennis exit(0); 3956b995818535af84c4a6829af7733684861f20144Jamie Gennis } 3966b995818535af84c4a6829af7733684861f20144Jamie Gennis 3976b995818535af84c4a6829af7733684861f20144Jamie Gennis if (getuid() != 0) { 3986b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "error: %s must be run as root.", argv[0]); 399bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis exit(1); 4006b995818535af84c4a6829af7733684861f20144Jamie Gennis } 4016b995818535af84c4a6829af7733684861f20144Jamie Gennis 4026b995818535af84c4a6829af7733684861f20144Jamie Gennis for (;;) { 4036b995818535af84c4a6829af7733684861f20144Jamie Gennis int ret; 4046b995818535af84c4a6829af7733684861f20144Jamie Gennis 40583fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown ret = getopt(argc, argv, "b:cidflst:wz"); 4066b995818535af84c4a6829af7733684861f20144Jamie Gennis 4076b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ret < 0) { 4086b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 4096b995818535af84c4a6829af7733684861f20144Jamie Gennis } 4106b995818535af84c4a6829af7733684861f20144Jamie Gennis 4116b995818535af84c4a6829af7733684861f20144Jamie Gennis switch(ret) { 412bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis case 'b': 413bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis g_traceBufferSizeKB = atoi(optarg); 414bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis break; 415bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 4166b995818535af84c4a6829af7733684861f20144Jamie Gennis case 'c': 4176b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceOverwrite = true; 4186b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 4196b995818535af84c4a6829af7733684861f20144Jamie Gennis 420585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis case 'i': 421585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis g_traceCpuIdle = true; 422585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis break; 423585c219b9b7c2e89b8db6707cacdaf29c362e7baJamie Gennis 424bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis case 'l': 425bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis g_traceGovernorLoad = true; 426bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis break; 427bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 42883fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown case 'd': 42983fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown g_traceDisk = true; 43083fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown break; 43183fdbb05c39b030ef1e5b3a7db79c617114c20f4Jeff Brown 432bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis case 'f': 433bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis g_traceCpuFrequency = true; 434bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis break; 435bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 4366b995818535af84c4a6829af7733684861f20144Jamie Gennis case 's': 4376b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceSchedSwitch = true; 4386b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 4396b995818535af84c4a6829af7733684861f20144Jamie Gennis 4406b995818535af84c4a6829af7733684861f20144Jamie Gennis case 't': 4416b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceDurationSeconds = atoi(optarg); 4426b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 4436b995818535af84c4a6829af7733684861f20144Jamie Gennis 4446b995818535af84c4a6829af7733684861f20144Jamie Gennis case 'w': 4456b995818535af84c4a6829af7733684861f20144Jamie Gennis g_traceWorkqueue = true; 4466b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 4476b995818535af84c4a6829af7733684861f20144Jamie Gennis 448eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis case 'z': 449eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis g_compress = true; 450eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis break; 451eb213e7201b7288df2d2ec7e785349d993828bd3Jamie Gennis 4526b995818535af84c4a6829af7733684861f20144Jamie Gennis default: 453bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis fprintf(stderr, "\n"); 4546b995818535af84c4a6829af7733684861f20144Jamie Gennis showHelp(argv[0]); 4556b995818535af84c4a6829af7733684861f20144Jamie Gennis exit(-1); 4566b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 4576b995818535af84c4a6829af7733684861f20144Jamie Gennis } 4586b995818535af84c4a6829af7733684861f20144Jamie Gennis } 4596b995818535af84c4a6829af7733684861f20144Jamie Gennis 4606b995818535af84c4a6829af7733684861f20144Jamie Gennis registerSigHandler(); 4616b995818535af84c4a6829af7733684861f20144Jamie Gennis 4626b995818535af84c4a6829af7733684861f20144Jamie Gennis bool ok = startTrace(); 4636b995818535af84c4a6829af7733684861f20144Jamie Gennis 4646b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ok) { 4656b995818535af84c4a6829af7733684861f20144Jamie Gennis printf("capturing trace..."); 4666b995818535af84c4a6829af7733684861f20144Jamie Gennis fflush(stdout); 4676b995818535af84c4a6829af7733684861f20144Jamie Gennis 4686b995818535af84c4a6829af7733684861f20144Jamie Gennis // We clear the trace after starting it because tracing gets enabled for 4696b995818535af84c4a6829af7733684861f20144Jamie Gennis // each CPU individually in the kernel. Having the beginning of the trace 4706b995818535af84c4a6829af7733684861f20144Jamie Gennis // contain entries from only one CPU can cause "begin" entries without a 4716b995818535af84c4a6829af7733684861f20144Jamie Gennis // matching "end" entry to show up if a task gets migrated from one CPU to 4726b995818535af84c4a6829af7733684861f20144Jamie Gennis // another. 4736b995818535af84c4a6829af7733684861f20144Jamie Gennis ok = clearTrace(); 4746b995818535af84c4a6829af7733684861f20144Jamie Gennis 4756b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ok) { 4766b995818535af84c4a6829af7733684861f20144Jamie Gennis // Sleep to allow the trace to be captured. 4776b995818535af84c4a6829af7733684861f20144Jamie Gennis struct timespec timeLeft; 4786b995818535af84c4a6829af7733684861f20144Jamie Gennis timeLeft.tv_sec = g_traceDurationSeconds; 4796b995818535af84c4a6829af7733684861f20144Jamie Gennis timeLeft.tv_nsec = 0; 4806b995818535af84c4a6829af7733684861f20144Jamie Gennis do { 4816b995818535af84c4a6829af7733684861f20144Jamie Gennis if (g_traceAborted) { 4826b995818535af84c4a6829af7733684861f20144Jamie Gennis break; 4836b995818535af84c4a6829af7733684861f20144Jamie Gennis } 4846b995818535af84c4a6829af7733684861f20144Jamie Gennis } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR); 4856b995818535af84c4a6829af7733684861f20144Jamie Gennis } 4866b995818535af84c4a6829af7733684861f20144Jamie Gennis } 4876b995818535af84c4a6829af7733684861f20144Jamie Gennis 4886b995818535af84c4a6829af7733684861f20144Jamie Gennis // Stop the trace and restore the default settings. 4896b995818535af84c4a6829af7733684861f20144Jamie Gennis stopTrace(); 4906b995818535af84c4a6829af7733684861f20144Jamie Gennis 4916b995818535af84c4a6829af7733684861f20144Jamie Gennis if (ok) { 4926b995818535af84c4a6829af7733684861f20144Jamie Gennis if (!g_traceAborted) { 4936b995818535af84c4a6829af7733684861f20144Jamie Gennis printf(" done\nTRACE:\n"); 4946b995818535af84c4a6829af7733684861f20144Jamie Gennis fflush(stdout); 4956b995818535af84c4a6829af7733684861f20144Jamie Gennis dumpTrace(); 4966b995818535af84c4a6829af7733684861f20144Jamie Gennis } else { 4976b995818535af84c4a6829af7733684861f20144Jamie Gennis printf("\ntrace aborted.\n"); 4986b995818535af84c4a6829af7733684861f20144Jamie Gennis fflush(stdout); 4996b995818535af84c4a6829af7733684861f20144Jamie Gennis } 5006b995818535af84c4a6829af7733684861f20144Jamie Gennis clearTrace(); 5016b995818535af84c4a6829af7733684861f20144Jamie Gennis } else { 5026b995818535af84c4a6829af7733684861f20144Jamie Gennis fprintf(stderr, "unable to start tracing\n"); 5036b995818535af84c4a6829af7733684861f20144Jamie Gennis } 5046b995818535af84c4a6829af7733684861f20144Jamie Gennis 505bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis // Reset the trace buffer size to 1. 506bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis setTraceBufferSizeKB(1); 507bc275ffc13e8c4e29ec08354c80a55df567dbab3Jamie Gennis 5086b995818535af84c4a6829af7733684861f20144Jamie Gennis return g_traceAborted ? 1 : 0; 5096b995818535af84c4a6829af7733684861f20144Jamie Gennis} 510