atrace.cpp revision 6eea6fb259a6d0b1c585d3267b8df7ca29a1206d
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> 194edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling#include <getopt.h> 20fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <signal.h> 21fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdarg.h> 22fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdbool.h> 23fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdio.h> 24fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <stdlib.h> 25fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <sys/sendfile.h> 26fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis#include <time.h> 277b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis#include <zlib.h> 28fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 296eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/IBinder.h> 306eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/IServiceManager.h> 316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <binder/Parcel.h> 326eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 336eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <cutils/properties.h> 346eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 356eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <utils/String8.h> 366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis#include <utils/Trace.h> 376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisusing namespace android; 396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 40ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0]))) 41ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown 426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisenum { MAX_SYS_FILES = 8 }; 436eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisconst char* k_traceTagsProperty = "debug.atrace.tags.enableflags"; 456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 466eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennistypedef enum { OPT, REQ } requiredness ; 476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstruct TracingCategory { 496eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // The name identifying the category. 506eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const char* name; 516eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 526eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // A longer description of the category. 536eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const char* longname; 546eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 556eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // The userland tracing tags that the category enables. 566eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis uint64_t tags; 576eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 586eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // The fname==NULL terminated list of /sys/ files that the category 596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // enables. 606eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis struct { 616eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // Whether the file must be writable in order to enable the tracing 626eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // category. 636eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis requiredness required; 646eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 656eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // The path to the enable file. 666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const char* path; 676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } sysfiles[MAX_SYS_FILES]; 686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}; 696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis/* Tracing categories */ 716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic const TracingCategory k_categories[] = { 726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "gfx", "Graphics", ATRACE_TAG_GRAPHICS, { } }, 736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "input", "Input", ATRACE_TAG_INPUT, { } }, 746eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "view", "View System", ATRACE_TAG_VIEW, { } }, 756eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "wm", "Window Manager", ATRACE_TAG_WINDOW_MANAGER, { } }, 766eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "am", "Activity Manager", ATRACE_TAG_ACTIVITY_MANAGER, { } }, 776eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "audio", "Audio", ATRACE_TAG_AUDIO, { } }, 786eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "video", "Video", ATRACE_TAG_VIDEO, { } }, 796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "camera", "Camera", ATRACE_TAG_CAMERA, { } }, 806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "sched", "CPU Scheduling", 0, { 816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/sched/sched_switch/enable" }, 826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable" }, 836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 846eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "freq", "CPU Frequency", 0, { 856eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable" }, 866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { OPT, "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable" }, 876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "membus", "Memory Bus Utilization", 0, { 896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/memory_bus/enable" }, 906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "idle", "CPU Idle", 0, { 926eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/power/cpu_idle/enable" }, 936eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "disk", "Disk I/O", 0, { 956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable" }, 966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable" }, 976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable" }, 986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable" }, 996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 1006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "load", "CPU Load", 0, { 1016eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable" }, 1026eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 1036eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "sync", "Synchronization", 0, { 1046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/sync/enable" }, 1056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 1066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { "workq", "Kernel Workqueues", 0, { 1076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { REQ, "/sys/kernel/debug/tracing/events/workqueue/enable" }, 1086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } }, 1096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis}; 1106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 111fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Command line options */ 112fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic int g_traceDurationSeconds = 5; 113fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceOverwrite = false; 114cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic int g_traceBufferSizeKB = 2048; 1157b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennisstatic bool g_compress = false; 11631be80f02cddda55e75614884038fa4645b694cdGlenn Kastenstatic bool g_nohup = false; 11731be80f02cddda55e75614884038fa4645b694cdGlenn Kastenstatic int g_initialSleepSecs = 0; 118fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 119fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Global state */ 120fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool g_traceAborted = false; 1216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool g_categoryEnables[NELEM(k_categories)] = {}; 122fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 123fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis/* Sys file paths */ 124fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_traceClockPath = 125fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace_clock"; 126fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 127cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic const char* k_traceBufferSizePath = 128cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis "/sys/kernel/debug/tracing/buffer_size_kb"; 129cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 130fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOverwriteEnablePath = 131fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/options/overwrite"; 132fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 133fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracingOnPath = 134fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/tracing_on"; 135fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 136fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic const char* k_tracePath = 137fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis "/sys/kernel/debug/tracing/trace"; 138fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 139e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis// Check whether a file exists. 140e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennisstatic bool fileExists(const char* filename) { 141e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis return access(filename, F_OK) != -1; 142e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis} 143e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis 1446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether a file is writable. 1456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool fileIsWritable(const char* filename) { 1466eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return access(filename, W_OK) != -1; 1476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis} 1486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 149fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Write a string to a file, returning true if the write was successful. 1506eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool writeStr(const char* filename, const char* str) 151fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 152fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int fd = open(filename, O_WRONLY); 153fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (fd == -1) { 154fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", filename, 155fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 156fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 157fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 158fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 159fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 160fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ssize_t len = strlen(str); 161fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (write(fd, str, len) != len) { 162fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error writing to %s: %s (%d)\n", filename, 163fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 164fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = false; 165fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 166fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 167fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(fd); 168fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 169fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 170fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 171fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 1726eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Enable or disable a kernel option by writing a "1" or a "0" into a /sys 1736eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// file. 174fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setKernelOptionEnable(const char* filename, bool enable) 175fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 176fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(filename, enable ? "1" : "0"); 177fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 178fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 1796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether the category is supported on the device with the current 1806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// rootness. A category is supported only if all its required /sys/ files are 1816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// writable and if enabling the category will enable one or more tracing tags 1826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// or /sys/ files. 1836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool isCategorySupported(const TracingCategory& category) 1843169533f1d11c4a7aa0cd6fa2aa04fc810db0de6Jamie Gennis{ 1856eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis bool ok = category.tags != 0; 1866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = 0; i < MAX_SYS_FILES; i++) { 1876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const char* path = category.sysfiles[i].path; 1886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis bool req = category.sysfiles[i].required == REQ; 1896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (path != NULL) { 1906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (req) { 1916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (!fileIsWritable(path)) { 1926eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return false; 1936eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else { 1946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok = true; 1956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 1966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else { 1976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok |= fileIsWritable(path); 1986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 1996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 200e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis } 201e8744fd4dce2881c83d69c084b6937d0397ace05Jamie Gennis return ok; 202cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 203cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 2046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Check whether the category would be supported on the device if the user 2056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// were root. This function assumes that root is able to write to any file 2066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// that exists. It performs the same logic as isCategorySupported, but it 2076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// uses file existance rather than writability in the /sys/ file checks. 2086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool isCategorySupportedForRoot(const TracingCategory& category) 2099ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling{ 2106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis bool ok = category.tags != 0; 2116eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = 0; i < MAX_SYS_FILES; i++) { 2126eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const char* path = category.sysfiles[i].path; 2136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis bool req = category.sysfiles[i].required == REQ; 2146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (path != NULL) { 2156eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (req) { 2166eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (!fileExists(path)) { 2176eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return false; 2186eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else { 2196eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok = true; 2206eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 2216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else { 2226eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok |= fileExists(path); 2236eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 2246eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 2259ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling } 2269ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling return ok; 2279ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling} 2289ba4baf178bb9dad3912403bfd9aee07c14da33aErik Gilling 2296eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Enable or disable overwriting of the kernel trace buffers. Disabling this 2306eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// will cause tracing to stop once the trace buffers have filled up. 2316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool setTraceOverwriteEnable(bool enable) 232ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown{ 2336eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable); 234ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown} 235ac9453d82e9077a8b02afa4e26ef9ff1f47b4ee9Jeff Brown 236fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable kernel tracing. 237fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setTracingEnabled(bool enable) 238fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 239fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return setKernelOptionEnable(k_tracingOnPath, enable); 240fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 241fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 242fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Clear the contents of the kernel trace. 243fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool clearTrace() 244fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 245fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = creat(k_tracePath, 0); 246fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 247fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath, 248fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 249fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return false; 250fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 251fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 252fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 253fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 254fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return true; 255fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 256fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 257cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis// Set the size of the kernel's trace buffer in kilobytes. 258cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennisstatic bool setTraceBufferSizeKB(int size) 259cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis{ 260cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis char str[32] = "1"; 261cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis int len; 262cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis if (size < 1) { 263cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis size = 1; 264cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis } 265cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis snprintf(str, 32, "%d", size); 266cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis return writeStr(k_traceBufferSizePath, str); 267cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis} 268cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 269fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable or disable the kernel's use of the global clock. Disabling the global 270fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// clock will result in the kernel using a per-CPU local clock. 271fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic bool setGlobalClockEnable(bool enable) 272fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 273fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return writeStr(k_traceClockPath, enable ? "global" : "local"); 274fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 275fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 2766eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Poke all the binder-enabled processes in the system to get them to re-read 2776eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// their system properties. 2786eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool pokeBinderServices() 2796eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{ 2806eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis sp<IServiceManager> sm = defaultServiceManager(); 2816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis Vector<String16> services = sm->listServices(); 2826eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (size_t i = 0; i < services.size(); i++) { 2836eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis sp<IBinder> obj = sm->checkService(services[i]); 2846eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (obj != NULL) { 2856eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis Parcel data; 2866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (obj->transact(IBinder::SYSPROPS_TRANSACTION, data, 2876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis NULL, 0) != OK) { 2886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (false) { 2896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // XXX: For some reason this fails on tablets trying to 2906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // poke the "phone" service. It's not clear whether some 2916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // are expected to fail. 2926eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis String8 svc(services[i]); 2936eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "error poking binder service %s\n", 2946eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis svc.string()); 2956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return false; 2966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 2976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 2986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 2996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return true; 3016eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis} 3026eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 3036eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Set the trace tags that userland tracing uses, and poke the running 3046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// processes to pick up the new value. 3056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool setTagsProperty(uint64_t tags) 3066eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{ 3076eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis char buf[64]; 3086eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis snprintf(buf, 64, "%#llx", tags); 3096eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (property_set(k_traceTagsProperty, buf) < 0) { 3106eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "error setting trace tags system property\n"); 3116eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return false; 3126eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3136eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return pokeBinderServices(); 3146eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis} 3156eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 3166eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Disable all /sys/ enable files. 3176eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool disableKernelTraceEvents() { 3186eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis bool ok = true; 3196eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = 0; i < NELEM(k_categories); i++) { 3206eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const TracingCategory &c = k_categories[i]; 3216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int j = 0; j < MAX_SYS_FILES; j++) { 3226eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const char* path = c.sysfiles[j].path; 3236eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (path != NULL && fileIsWritable(path)) { 3246eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok &= setKernelOptionEnable(path, false); 3256eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3266eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3276eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3286eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return ok; 3296eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis} 3306eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 331fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Enable tracing in the kernel. 3326eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool startTrace() 333fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 334fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis bool ok = true; 335fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 3366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // Set up the tracing options. 337fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTraceOverwriteEnable(g_traceOverwrite); 338cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis ok &= setTraceBufferSizeKB(g_traceBufferSizeKB); 339fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setGlobalClockEnable(true); 340fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 3416eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // Set up the tags property. 3426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis uint64_t tags = 0; 3436eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = 0; i < NELEM(k_categories); i++) { 3446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (g_categoryEnables[i]) { 3456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const TracingCategory &c = k_categories[i]; 3466eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis tags |= c.tags; 3476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3496eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok &= setTagsProperty(tags); 3506eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 3516eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // Disable all the sysfs enables. This is done as a separate loop from 3526eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // the enables to allow the same enable to exist in multiple categories. 3536eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok &= disableKernelTraceEvents(); 3546eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 3556eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // Enable all the sysfs enables that are in an enabled category. 3566eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = 0; i < NELEM(k_categories); i++) { 3576eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (g_categoryEnables[i]) { 3586eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const TracingCategory &c = k_categories[i]; 3596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int j = 0; j < MAX_SYS_FILES; j++) { 3606eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const char* path = c.sysfiles[j].path; 3616eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis bool required = c.sysfiles[j].required == REQ; 3626eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (path != NULL) { 3636eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (fileIsWritable(path)) { 3646eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok &= setKernelOptionEnable(path, true); 3656eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else if (required) { 3666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "error writing file %s\n", path); 3676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ok = false; 3686eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3696eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3706eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3716eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 3724b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis } 3734b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis 374fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Enable tracing. 375fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok &= setTracingEnabled(true); 376fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 377fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return ok; 378fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 379fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 380fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Disable tracing in the kernel. 3816eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void stopTrace() 382fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 383fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Disable tracing. 384fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTracingEnabled(false); 385fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 3866eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // Disable all tracing that we're able to. 3876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis disableKernelTraceEvents(); 3886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 3896eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis // Disable all the trace tags. 3906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis setTagsProperty(0); 3916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 392fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Set the options back to their defaults. 393fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setTraceOverwriteEnable(true); 394fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis setGlobalClockEnable(false); 395cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 396cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // Note that we can't reset the trace buffer size here because that would 397cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // clear the trace before we've read it. 398fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 399fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 400fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis// Read the current kernel trace and write it to stdout. 401fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisstatic void dumpTrace() 402fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 403fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int traceFD = open(k_tracePath, O_RDWR); 404fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (traceFD == -1) { 405fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath, 406fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis strerror(errno), errno); 407fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return; 408fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 409fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 4107b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (g_compress) { 4117b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis z_stream zs; 4127b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis uint8_t *in, *out; 4137b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis int result, flush; 4147b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4157b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis bzero(&zs, sizeof(zs)); 4167b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = deflateInit(&zs, Z_DEFAULT_COMPRESSION); 4177b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_OK) { 4187b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error initializing zlib: %d\n", result); 4197b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis close(traceFD); 4207b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis return; 4217b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4227b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4237b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis const size_t bufSize = 64*1024; 4247b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis in = (uint8_t*)malloc(bufSize); 4257b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis out = (uint8_t*)malloc(bufSize); 4267b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis flush = Z_NO_FLUSH; 4277b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4287b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_out = out; 4297b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; 4307b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4317b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis do { 4327b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4337b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_in == 0) { 4347b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis // More input is needed. 4357b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = read(traceFD, in, bufSize); 4367b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result < 0) { 4377b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error reading trace: %s (%d)\n", 4387b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 4397b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = Z_STREAM_END; 4407b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 4417b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else if (result == 0) { 4427b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis flush = Z_FINISH; 4437b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else { 4447b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_in = in; 4457b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_in = result; 4467b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4477b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4487b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4497b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_out == 0) { 4507b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis // Need to write the output. 4517b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = write(STDOUT_FILENO, out, bufSize); 4527b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if ((size_t)result < bufSize) { 4537b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 4547b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 4557b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = Z_STREAM_END; // skip deflate error message 4567b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; // skip the final write 4577b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 4587b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4597b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.next_out = out; 4607b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis zs.avail_out = bufSize; 4617b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4627b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4637b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } while ((result = deflate(&zs, flush)) == Z_OK); 4647b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4657b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_STREAM_END) { 4667b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error deflating trace: %s\n", zs.msg); 4677b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4687b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4697b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (zs.avail_out < bufSize) { 4707b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis size_t bytes = bufSize - zs.avail_out; 4717b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = write(STDOUT_FILENO, out, bytes); 4727b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if ((size_t)result < bytes) { 4737b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error writing deflated trace: %s (%d)\n", 4747b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis strerror(errno), errno); 4757b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4767b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4777b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4787b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis result = deflateEnd(&zs); 4797b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (result != Z_OK) { 4807b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error cleaning up zlib: %d\n", result); 4817b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 4827b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 4837b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis free(in); 4847b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis free(out); 4857b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } else { 4867b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis ssize_t sent = 0; 4877b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0); 4887b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis if (sent == -1) { 4897b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno), 4907b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis errno); 4917b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis } 492fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 493fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 494fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis close(traceFD); 495fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 496fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 4976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void handleSignal(int signo) 498fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 49931be80f02cddda55e75614884038fa4645b694cdGlenn Kasten if (!g_nohup) { 50031be80f02cddda55e75614884038fa4645b694cdGlenn Kasten g_traceAborted = true; 50131be80f02cddda55e75614884038fa4645b694cdGlenn Kasten } 502fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 503fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 5046eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void registerSigHandler() 5056eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{ 506fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct sigaction sa; 507fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigemptyset(&sa.sa_mask); 508fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_flags = 0; 509fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sa.sa_handler = handleSignal; 510fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGHUP, &sa, NULL); 511fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGINT, &sa, NULL); 512fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGQUIT, &sa, NULL); 513fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis sigaction(SIGTERM, &sa, NULL); 514fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 515fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 5166eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic bool setCategoryEnable(const char* name, bool enable) 5176eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{ 5186eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = 0; i < NELEM(k_categories); i++) { 5196eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const TracingCategory& c = k_categories[i]; 5206eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (strcmp(name, c.name) == 0) { 5216eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (isCategorySupported(c)) { 5226eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis g_categoryEnables[i] = enable; 5236eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return true; 5246eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else { 5256eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (isCategorySupportedForRoot(c)) { 5266eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "error: category \"%s\" requires root " 5276eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis "privileges.\n", name); 5286eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else { 5296eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "error: category \"%s\" is not supported " 5306eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis "on this device.\n", name); 5316eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 5326eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return false; 5336eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 5346eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 5356eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 5366eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "error: unknown tracing category \"%s\"\n", name); 5376eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis return false; 5386eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis} 5396eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 5406eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void listSupportedCategories() 5416eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{ 5426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = 0; i < NELEM(k_categories); i++) { 5436eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis const TracingCategory& c = k_categories[i]; 5446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (isCategorySupported(c)) { 5456eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis printf(" %10s - %s\n", c.name, c.longname); 5466eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 5476eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 5486eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis} 5496eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 5506eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis// Print the command usage help to stderr. 5516eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennisstatic void showHelp(const char *cmd) 5526eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis{ 5536eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "usage: %s [options] [categories...]\n", cmd); 5546eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "options include:\n" 5556eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " -b N use a trace buffer size of N KB\n" 5566eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " -c trace into a circular buffer\n" 5576eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " -n ignore signals\n" 5586eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " -s N sleep for N seconds before tracing [default 0]\n" 5596eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " -t N trace for N seconds [defualt 5]\n" 5606eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " -z compress the trace dump\n" 5616eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " --async_start start circular trace and return immediatly\n" 5626eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " --async_dump dump the current contents of circular trace buffer\n" 5636eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " --async_stop stop tracing and dump the current contents of circular\n" 5646eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis " trace buffer\n" 5656eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ); 5666eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis} 5676eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis 568fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennisint main(int argc, char **argv) 569fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis{ 5704edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling bool async = false; 5714edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling bool traceStart = true; 5724edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling bool traceStop = true; 5734edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling bool traceDump = true; 5744b23eefd72501b358c61fb1a7096a2a94e5ea351Jamie Gennis 575fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (argc == 2 && 0 == strcmp(argv[1], "--help")) { 576fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 577fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(0); 578fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 579fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 580fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis for (;;) { 581fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis int ret; 5824edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling int option_index = 0; 5834edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling static struct option long_options[] = { 5844edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling {"async_start", no_argument, 0, 0 }, 5854edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling {"async_stop", no_argument, 0, 0 }, 5864edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling {"async_dump", no_argument, 0, 0 }, 5876eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis {"list_categories", no_argument, 0, 0 }, 5886eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis { 0, 0, 0, 0 } 5894edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling }; 590fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 5916eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis ret = getopt_long(argc, argv, "b:cns:t:z", 5924edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling long_options, &option_index); 593fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 594fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (ret < 0) { 5956eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis for (int i = optind; i < argc; i++) { 5966eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis if (!setCategoryEnable(argv[i], true)) { 5976eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis fprintf(stderr, "error enabling tracing category \"%s\"\n", argv[i]); 5986eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis exit(1); 5996eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 6006eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } 601fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 602fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 603fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 604fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis switch(ret) { 605cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis case 'b': 606cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis g_traceBufferSizeKB = atoi(optarg); 607cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis break; 608cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 609fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 'c': 610fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceOverwrite = true; 611fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 612fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 61331be80f02cddda55e75614884038fa4645b694cdGlenn Kasten case 'n': 61431be80f02cddda55e75614884038fa4645b694cdGlenn Kasten g_nohup = true; 61531be80f02cddda55e75614884038fa4645b694cdGlenn Kasten break; 61631be80f02cddda55e75614884038fa4645b694cdGlenn Kasten 617fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 's': 61831be80f02cddda55e75614884038fa4645b694cdGlenn Kasten g_initialSleepSecs = atoi(optarg); 61931be80f02cddda55e75614884038fa4645b694cdGlenn Kasten break; 62031be80f02cddda55e75614884038fa4645b694cdGlenn Kasten 621fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis case 't': 622fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis g_traceDurationSeconds = atoi(optarg); 623fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 624fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 6257b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis case 'z': 6267b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis g_compress = true; 6277b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis break; 6287b5170b249c1d312cfe3b5658b6c140b2a48226fJamie Gennis 6294edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling case 0: 6304edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling if (!strcmp(long_options[option_index].name, "async_start")) { 6314edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling async = true; 6324edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling traceStop = false; 6334edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling traceDump = false; 6344edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling g_traceOverwrite = true; 6354edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling } else if (!strcmp(long_options[option_index].name, "async_stop")) { 6364edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling async = true; 6374edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling traceStop = false; 6384edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling } else if (!strcmp(long_options[option_index].name, "async_dump")) { 6394edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling async = true; 6404edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling traceStart = false; 6414edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling traceStop = false; 6426eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis } else if (!strcmp(long_options[option_index].name, "list_categories")) { 6436eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis listSupportedCategories(); 6446eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis exit(0); 6454edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling } 6464edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling break; 6474edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling 648fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis default: 649cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis fprintf(stderr, "\n"); 650fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis showHelp(argv[0]); 651fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis exit(-1); 652fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 653fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 654fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 655fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 656fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis registerSigHandler(); 657fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 65831be80f02cddda55e75614884038fa4645b694cdGlenn Kasten if (g_initialSleepSecs > 0) { 65931be80f02cddda55e75614884038fa4645b694cdGlenn Kasten sleep(g_initialSleepSecs); 66031be80f02cddda55e75614884038fa4645b694cdGlenn Kasten } 66131be80f02cddda55e75614884038fa4645b694cdGlenn Kasten 6626eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis bool ok = startTrace(); 663fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 6644edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling if (ok && traceStart) { 665fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("capturing trace..."); 666fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 667fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 668fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // We clear the trace after starting it because tracing gets enabled for 669fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // each CPU individually in the kernel. Having the beginning of the trace 670fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // contain entries from only one CPU can cause "begin" entries without a 671fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // matching "end" entry to show up if a task gets migrated from one CPU to 672fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // another. 673fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis ok = clearTrace(); 674fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 6754edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling if (ok && !async) { 676fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Sleep to allow the trace to be captured. 677fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis struct timespec timeLeft; 678fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_sec = g_traceDurationSeconds; 679fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis timeLeft.tv_nsec = 0; 680fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis do { 681fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (g_traceAborted) { 682fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis break; 683fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 684fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR); 685fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 686fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 687fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 688fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis // Stop the trace and restore the default settings. 6894edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling if (traceStop) 6906eea6fb259a6d0b1c585d3267b8df7ca29a1206dJamie Gennis stopTrace(); 691fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 6924edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling if (ok && traceDump) { 693fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis if (!g_traceAborted) { 694fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf(" done\nTRACE:\n"); 695fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 696fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis dumpTrace(); 697fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } else { 698fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis printf("\ntrace aborted.\n"); 699fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fflush(stdout); 700fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 701fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis clearTrace(); 7024edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling } else if (!ok) { 703fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis fprintf(stderr, "unable to start tracing\n"); 704fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis } 705fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis 706cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis // Reset the trace buffer size to 1. 7074edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling if (traceStop) 7084edbd078cddcc1cbe59156a0e7ece01de75156e0Erik Gilling setTraceBufferSizeKB(1); 709cc24c8e6b48c2eb204bf3d7f974dbff6dc0cc862Jamie Gennis 710fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis return g_traceAborted ? 1 : 0; 711fb31ba69282e34df62005ec63afda2b8ec69533eJamie Gennis} 712