From b1ce49b2ed9ea953a7f534b4f36b6acb56fc0749 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Wed, 20 Aug 2014 14:28:47 -0700 Subject: [PATCH] atrace: avoid unnecessary writes to trace_clock Writing to trace_clock erases the trace buffer, even if the value hasn't changed. This prevents use of --async_start and --async_dump to leave background tracing running and dump after an even that needs debugging, because --async_dump writes to trace_clock and resets the buffer before it can read it. Read and parse the current value from trace_clock before writing, and skip the write if the value isn't changing. Change-Id: Ia2ec5bb654fb0bd179771b511ff261731ba47dca --- cmds/atrace/atrace.cpp | 47 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/cmds/atrace/atrace.cpp b/cmds/atrace/atrace.cpp index fb401931f..9e5c91068 100644 --- a/cmds/atrace/atrace.cpp +++ b/cmds/atrace/atrace.cpp @@ -341,11 +341,56 @@ static bool setTraceBufferSizeKB(int size) return writeStr(k_traceBufferSizePath, str); } +// Read the trace_clock sysfs file and return true if it matches the requested +// value. The trace_clock file format is: +// local [global] counter uptime perf +static bool isTraceClock(const char *mode) +{ + int fd = open(k_traceClockPath, O_RDONLY); + if (fd == -1) { + fprintf(stderr, "error opening %s: %s (%d)\n", k_traceClockPath, + strerror(errno), errno); + return false; + } + + char buf[4097]; + ssize_t n = read(fd, buf, 4096); + close(fd); + if (n == -1) { + fprintf(stderr, "error reading %s: %s (%d)\n", k_traceClockPath, + strerror(errno), errno); + return false; + } + buf[n] = '\0'; + + char *start = strchr(buf, '['); + if (start == NULL) { + return false; + } + start++; + + char *end = strchr(start, ']'); + if (end == NULL) { + return false; + } + *end = '\0'; + + return strcmp(mode, start) == 0; +} + // Enable or disable the kernel's use of the global clock. Disabling the global // clock will result in the kernel using a per-CPU local clock. +// Any write to the trace_clock sysfs file will reset the buffer, so only +// update it if the requested value is not the current value. static bool setGlobalClockEnable(bool enable) { - return writeStr(k_traceClockPath, enable ? "global" : "local"); + const char *clock = enable ? "global" : "local"; + + if (isTraceClock(clock)) { + return true; + } + + return writeStr(k_traceClockPath, clock); } static bool setPrintTgidEnableIfPresent(bool enable)