blob: 381a4ed9d7ee96ba23180c2528296cef7f0f7933 [file] [log] [blame]
Jamie Gennisfb31ba62012-02-23 14:16:05 -08001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <errno.h>
18#include <fcntl.h>
19#include <signal.h>
20#include <stdarg.h>
21#include <stdbool.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <sys/sendfile.h>
25#include <time.h>
Jamie Gennis7b5170b2012-04-28 19:06:49 -070026#include <zlib.h>
Jamie Gennisfb31ba62012-02-23 14:16:05 -080027
Jeff Brownac9453d2012-05-22 18:58:46 -070028#define NELEM(x) ((int) (sizeof(x) / sizeof((x)[0])))
29
Jamie Gennisfb31ba62012-02-23 14:16:05 -080030/* Command line options */
31static int g_traceDurationSeconds = 5;
32static bool g_traceSchedSwitch = false;
Erik Gilling99be77c2012-09-20 17:55:10 -070033static bool g_traceFrequency = false;
34static bool g_traceBusUtilization = false;
Jamie Gennis31695332012-05-07 17:58:44 -070035static bool g_traceCpuIdle = false;
Jeff Brownac9453d2012-05-22 18:58:46 -070036static bool g_traceDisk = false;
Jamie Genniscc24c8e2012-03-05 19:10:37 -080037static bool g_traceGovernorLoad = false;
Jamie Gennisfb31ba62012-02-23 14:16:05 -080038static bool g_traceWorkqueue = false;
39static bool g_traceOverwrite = false;
Jamie Genniscc24c8e2012-03-05 19:10:37 -080040static int g_traceBufferSizeKB = 2048;
Jamie Gennis7b5170b2012-04-28 19:06:49 -070041static bool g_compress = false;
Jamie Gennisfb31ba62012-02-23 14:16:05 -080042
43/* Global state */
44static bool g_traceAborted = false;
45
46/* Sys file paths */
47static const char* k_traceClockPath =
48 "/sys/kernel/debug/tracing/trace_clock";
49
Jamie Genniscc24c8e2012-03-05 19:10:37 -080050static const char* k_traceBufferSizePath =
51 "/sys/kernel/debug/tracing/buffer_size_kb";
52
Jamie Gennisfb31ba62012-02-23 14:16:05 -080053static const char* k_tracingOverwriteEnablePath =
54 "/sys/kernel/debug/tracing/options/overwrite";
55
56static const char* k_schedSwitchEnablePath =
57 "/sys/kernel/debug/tracing/events/sched/sched_switch/enable";
58
Jamie Gennis4b23eef2012-06-07 16:27:03 -070059static const char* k_schedWakeupEnablePath =
60 "/sys/kernel/debug/tracing/events/sched/sched_wakeup/enable";
61
Erik Gilling99be77c2012-09-20 17:55:10 -070062static const char* k_memoryBusEnablePath =
63 "/sys/kernel/debug/tracing/events/memory_bus/enable";
64
Jamie Genniscc24c8e2012-03-05 19:10:37 -080065static const char* k_cpuFreqEnablePath =
66 "/sys/kernel/debug/tracing/events/power/cpu_frequency/enable";
67
Erik Gilling99be77c2012-09-20 17:55:10 -070068static const char *k_clockSetRateEnablePath =
69 "/sys/kernel/debug/tracing/events/power/clock_set_rate/enable";
70
Jamie Gennis31695332012-05-07 17:58:44 -070071static const char* k_cpuIdleEnablePath =
72 "/sys/kernel/debug/tracing/events/power/cpu_idle/enable";
73
Jamie Genniscc24c8e2012-03-05 19:10:37 -080074static const char* k_governorLoadEnablePath =
75 "/sys/kernel/debug/tracing/events/cpufreq_interactive/enable";
76
Jamie Gennisfb31ba62012-02-23 14:16:05 -080077static const char* k_workqueueEnablePath =
78 "/sys/kernel/debug/tracing/events/workqueue/enable";
79
Jeff Brownac9453d2012-05-22 18:58:46 -070080static const char* k_diskEnablePaths[] = {
81 "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_enter/enable",
82 "/sys/kernel/debug/tracing/events/ext4/ext4_sync_file_exit/enable",
83 "/sys/kernel/debug/tracing/events/block/block_rq_issue/enable",
84 "/sys/kernel/debug/tracing/events/block/block_rq_complete/enable",
85};
86
Jamie Gennisfb31ba62012-02-23 14:16:05 -080087static const char* k_tracingOnPath =
88 "/sys/kernel/debug/tracing/tracing_on";
89
90static const char* k_tracePath =
91 "/sys/kernel/debug/tracing/trace";
92
93static const char* k_traceMarkerPath =
94 "/sys/kernel/debug/tracing/trace_marker";
95
96// Write a string to a file, returning true if the write was successful.
97bool writeStr(const char* filename, const char* str)
98{
99 int fd = open(filename, O_WRONLY);
100 if (fd == -1) {
101 fprintf(stderr, "error opening %s: %s (%d)\n", filename,
102 strerror(errno), errno);
103 return false;
104 }
105
106 bool ok = true;
107 ssize_t len = strlen(str);
108 if (write(fd, str, len) != len) {
109 fprintf(stderr, "error writing to %s: %s (%d)\n", filename,
110 strerror(errno), errno);
111 ok = false;
112 }
113
114 close(fd);
115
116 return ok;
117}
118
119// Enable or disable a kernel option by writing a "1" or a "0" into a /sys file.
120static bool setKernelOptionEnable(const char* filename, bool enable)
121{
122 return writeStr(filename, enable ? "1" : "0");
123}
124
Jeff Brownac9453d2012-05-22 18:58:46 -0700125// Enable or disable a collection of kernel options by writing a "1" or a "0" into each /sys file.
126static bool setMultipleKernelOptionsEnable(const char** filenames, size_t count, bool enable)
127{
128 bool result = true;
129 for (size_t i = 0; i < count; i++) {
130 result &= setKernelOptionEnable(filenames[i], enable);
131 }
132 return result;
133}
134
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800135// Enable or disable overwriting of the kernel trace buffers. Disabling this
136// will cause tracing to stop once the trace buffers have filled up.
137static bool setTraceOverwriteEnable(bool enable)
138{
139 return setKernelOptionEnable(k_tracingOverwriteEnablePath, enable);
140}
141
142// Enable or disable tracing of the kernel scheduler switching.
143static bool setSchedSwitchTracingEnable(bool enable)
144{
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700145 bool ok = true;
146 ok &= setKernelOptionEnable(k_schedSwitchEnablePath, enable);
147 ok &= setKernelOptionEnable(k_schedWakeupEnablePath, enable);
148 return ok;
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800149}
150
Erik Gilling99be77c2012-09-20 17:55:10 -0700151// Enable or disable tracing of the Bus utilization.
152static bool setBusUtilizationTracingEnable(bool enable)
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800153{
Erik Gilling99be77c2012-09-20 17:55:10 -0700154 bool ok = false;
155 // these can be platform specific so make sure that at least
156 // one succeeds.
157 ok |= setKernelOptionEnable(k_memoryBusEnablePath, enable);
158 return ok;
159}
160
161// Enable or disable tracing of the CPU clock frequency.
162static bool setFrequencyTracingEnable(bool enable)
163{
164 bool ok = true;
165 ok &= setKernelOptionEnable(k_cpuFreqEnablePath, enable);
166 ok &= setKernelOptionEnable(k_clockSetRateEnablePath, enable);
167 return ok;
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800168}
169
Jamie Gennis31695332012-05-07 17:58:44 -0700170// Enable or disable tracing of CPU idle events.
171static bool setCpuIdleTracingEnable(bool enable)
172{
173 return setKernelOptionEnable(k_cpuIdleEnablePath, enable);
174}
175
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800176// Enable or disable tracing of the interactive CPU frequency governor's idea of
177// the CPU load.
178static bool setGovernorLoadTracingEnable(bool enable)
179{
180 return setKernelOptionEnable(k_governorLoadEnablePath, enable);
181}
182
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800183// Enable or disable tracing of the kernel workqueues.
184static bool setWorkqueueTracingEnabled(bool enable)
185{
186 return setKernelOptionEnable(k_workqueueEnablePath, enable);
187}
188
Jeff Brownac9453d2012-05-22 18:58:46 -0700189// Enable or disable tracing of disk I/O.
190static bool setDiskTracingEnabled(bool enable)
191{
192 return setMultipleKernelOptionsEnable(k_diskEnablePaths, NELEM(k_diskEnablePaths), enable);
193}
194
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800195// Enable or disable kernel tracing.
196static bool setTracingEnabled(bool enable)
197{
198 return setKernelOptionEnable(k_tracingOnPath, enable);
199}
200
201// Clear the contents of the kernel trace.
202static bool clearTrace()
203{
204 int traceFD = creat(k_tracePath, 0);
205 if (traceFD == -1) {
206 fprintf(stderr, "error truncating %s: %s (%d)\n", k_tracePath,
207 strerror(errno), errno);
208 return false;
209 }
210
211 close(traceFD);
212
213 return true;
214}
215
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800216// Set the size of the kernel's trace buffer in kilobytes.
217static bool setTraceBufferSizeKB(int size)
218{
219 char str[32] = "1";
220 int len;
221 if (size < 1) {
222 size = 1;
223 }
224 snprintf(str, 32, "%d", size);
225 return writeStr(k_traceBufferSizePath, str);
226}
227
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800228// Enable or disable the kernel's use of the global clock. Disabling the global
229// clock will result in the kernel using a per-CPU local clock.
230static bool setGlobalClockEnable(bool enable)
231{
232 return writeStr(k_traceClockPath, enable ? "global" : "local");
233}
234
Jamie Gennisfe312b92012-04-09 17:33:45 -0700235// Check whether a file exists.
236static bool fileExists(const char* filename) {
237 return access(filename, F_OK) != -1;
238}
239
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800240// Enable tracing in the kernel.
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700241static bool startTrace(bool isRoot)
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800242{
243 bool ok = true;
244
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700245 // Set up the tracing options that don't require root.
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800246 ok &= setTraceOverwriteEnable(g_traceOverwrite);
247 ok &= setSchedSwitchTracingEnable(g_traceSchedSwitch);
Erik Gilling99be77c2012-09-20 17:55:10 -0700248 ok &= setBusUtilizationTracingEnable(g_traceBusUtilization);
249 ok &= setFrequencyTracingEnable(g_traceFrequency);
Jamie Gennis31695332012-05-07 17:58:44 -0700250 ok &= setCpuIdleTracingEnable(g_traceCpuIdle);
Jamie Gennisfe312b92012-04-09 17:33:45 -0700251 if (fileExists(k_governorLoadEnablePath) || g_traceGovernorLoad) {
252 ok &= setGovernorLoadTracingEnable(g_traceGovernorLoad);
253 }
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800254 ok &= setTraceBufferSizeKB(g_traceBufferSizeKB);
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800255 ok &= setGlobalClockEnable(true);
256
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700257 // Set up the tracing options that do require root. The options that
258 // require root should have errored out earlier if we're not running as
259 // root.
260 if (isRoot) {
261 ok &= setWorkqueueTracingEnabled(g_traceWorkqueue);
262 ok &= setDiskTracingEnabled(g_traceDisk);
263 }
264
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800265 // Enable tracing.
266 ok &= setTracingEnabled(true);
267
268 if (!ok) {
269 fprintf(stderr, "error: unable to start trace\n");
270 }
271
272 return ok;
273}
274
275// Disable tracing in the kernel.
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700276static void stopTrace(bool isRoot)
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800277{
278 // Disable tracing.
279 setTracingEnabled(false);
280
281 // Set the options back to their defaults.
282 setTraceOverwriteEnable(true);
283 setSchedSwitchTracingEnable(false);
Erik Gilling99be77c2012-09-20 17:55:10 -0700284 setBusUtilizationTracingEnable(false);
285 setFrequencyTracingEnable(false);
Jamie Gennisfe312b92012-04-09 17:33:45 -0700286 if (fileExists(k_governorLoadEnablePath)) {
287 setGovernorLoadTracingEnable(false);
288 }
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800289 setGlobalClockEnable(false);
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800290
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700291 if (isRoot) {
292 setWorkqueueTracingEnabled(false);
293 setDiskTracingEnabled(false);
294 }
295
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800296 // Note that we can't reset the trace buffer size here because that would
297 // clear the trace before we've read it.
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800298}
299
300// Read the current kernel trace and write it to stdout.
301static void dumpTrace()
302{
303 int traceFD = open(k_tracePath, O_RDWR);
304 if (traceFD == -1) {
305 fprintf(stderr, "error opening %s: %s (%d)\n", k_tracePath,
306 strerror(errno), errno);
307 return;
308 }
309
Jamie Gennis7b5170b2012-04-28 19:06:49 -0700310 if (g_compress) {
311 z_stream zs;
312 uint8_t *in, *out;
313 int result, flush;
314
315 bzero(&zs, sizeof(zs));
316 result = deflateInit(&zs, Z_DEFAULT_COMPRESSION);
317 if (result != Z_OK) {
318 fprintf(stderr, "error initializing zlib: %d\n", result);
319 close(traceFD);
320 return;
321 }
322
323 const size_t bufSize = 64*1024;
324 in = (uint8_t*)malloc(bufSize);
325 out = (uint8_t*)malloc(bufSize);
326 flush = Z_NO_FLUSH;
327
328 zs.next_out = out;
329 zs.avail_out = bufSize;
330
331 do {
332
333 if (zs.avail_in == 0) {
334 // More input is needed.
335 result = read(traceFD, in, bufSize);
336 if (result < 0) {
337 fprintf(stderr, "error reading trace: %s (%d)\n",
338 strerror(errno), errno);
339 result = Z_STREAM_END;
340 break;
341 } else if (result == 0) {
342 flush = Z_FINISH;
343 } else {
344 zs.next_in = in;
345 zs.avail_in = result;
346 }
347 }
348
349 if (zs.avail_out == 0) {
350 // Need to write the output.
351 result = write(STDOUT_FILENO, out, bufSize);
352 if ((size_t)result < bufSize) {
353 fprintf(stderr, "error writing deflated trace: %s (%d)\n",
354 strerror(errno), errno);
355 result = Z_STREAM_END; // skip deflate error message
356 zs.avail_out = bufSize; // skip the final write
357 break;
358 }
359 zs.next_out = out;
360 zs.avail_out = bufSize;
361 }
362
363 } while ((result = deflate(&zs, flush)) == Z_OK);
364
365 if (result != Z_STREAM_END) {
366 fprintf(stderr, "error deflating trace: %s\n", zs.msg);
367 }
368
369 if (zs.avail_out < bufSize) {
370 size_t bytes = bufSize - zs.avail_out;
371 result = write(STDOUT_FILENO, out, bytes);
372 if ((size_t)result < bytes) {
373 fprintf(stderr, "error writing deflated trace: %s (%d)\n",
374 strerror(errno), errno);
375 }
376 }
377
378 result = deflateEnd(&zs);
379 if (result != Z_OK) {
380 fprintf(stderr, "error cleaning up zlib: %d\n", result);
381 }
382
383 free(in);
384 free(out);
385 } else {
386 ssize_t sent = 0;
387 while ((sent = sendfile(STDOUT_FILENO, traceFD, NULL, 64*1024*1024)) > 0);
388 if (sent == -1) {
389 fprintf(stderr, "error dumping trace: %s (%d)\n", strerror(errno),
390 errno);
391 }
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800392 }
393
394 close(traceFD);
395}
396
397// Print the command usage help to stderr.
398static void showHelp(const char *cmd)
399{
400 fprintf(stderr, "usage: %s [options]\n", cmd);
401 fprintf(stderr, "options include:\n"
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800402 " -b N use a trace buffer size of N KB\n"
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800403 " -c trace into a circular buffer\n"
Jeff Brownac9453d2012-05-22 18:58:46 -0700404 " -d trace disk I/O\n"
Erik Gilling99be77c2012-09-20 17:55:10 -0700405 " -f trace clock frequency changes\n"
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800406 " -l trace CPU frequency governor load\n"
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800407 " -s trace the kernel scheduler switches\n"
408 " -t N trace for N seconds [defualt 5]\n"
Erik Gilling99be77c2012-09-20 17:55:10 -0700409 " -u trace bus utilization\n"
Jamie Gennis7b5170b2012-04-28 19:06:49 -0700410 " -w trace the kernel workqueue\n"
411 " -z compress the trace dump\n");
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800412}
413
414static void handleSignal(int signo) {
415 g_traceAborted = true;
416}
417
418static void registerSigHandler() {
419 struct sigaction sa;
420 sigemptyset(&sa.sa_mask);
421 sa.sa_flags = 0;
422 sa.sa_handler = handleSignal;
423 sigaction(SIGHUP, &sa, NULL);
424 sigaction(SIGINT, &sa, NULL);
425 sigaction(SIGQUIT, &sa, NULL);
426 sigaction(SIGTERM, &sa, NULL);
427}
428
429int main(int argc, char **argv)
430{
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700431 bool isRoot = (getuid() == 0);
432
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800433 if (argc == 2 && 0 == strcmp(argv[1], "--help")) {
434 showHelp(argv[0]);
435 exit(0);
436 }
437
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800438 for (;;) {
439 int ret;
440
Erik Gilling99be77c2012-09-20 17:55:10 -0700441 ret = getopt(argc, argv, "b:cidflst:uwz");
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800442
443 if (ret < 0) {
444 break;
445 }
446
447 switch(ret) {
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800448 case 'b':
449 g_traceBufferSizeKB = atoi(optarg);
450 break;
451
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800452 case 'c':
453 g_traceOverwrite = true;
454 break;
455
Jamie Gennis31695332012-05-07 17:58:44 -0700456 case 'i':
457 g_traceCpuIdle = true;
458 break;
459
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800460 case 'l':
461 g_traceGovernorLoad = true;
462 break;
463
Jeff Brownac9453d2012-05-22 18:58:46 -0700464 case 'd':
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700465 if (!isRoot) {
466 fprintf(stderr, "error: tracing disk activity requires root privileges\n");
467 exit(1);
468 }
Jeff Brownac9453d2012-05-22 18:58:46 -0700469 g_traceDisk = true;
470 break;
471
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800472 case 'f':
Erik Gilling99be77c2012-09-20 17:55:10 -0700473 g_traceFrequency = true;
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800474 break;
475
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800476 case 's':
477 g_traceSchedSwitch = true;
478 break;
479
480 case 't':
481 g_traceDurationSeconds = atoi(optarg);
482 break;
483
Erik Gilling99be77c2012-09-20 17:55:10 -0700484 case 'u':
485 if (!isRoot) {
486 fprintf(stderr, "error: tracing bus utilization requires root privileges\n");
487 exit(1);
488 }
489 g_traceBusUtilization = true;
490 break;
491
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800492 case 'w':
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700493 if (!isRoot) {
494 fprintf(stderr, "error: tracing kernel work queues requires root privileges\n");
495 exit(1);
496 }
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800497 g_traceWorkqueue = true;
498 break;
499
Jamie Gennis7b5170b2012-04-28 19:06:49 -0700500 case 'z':
501 g_compress = true;
502 break;
503
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800504 default:
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800505 fprintf(stderr, "\n");
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800506 showHelp(argv[0]);
507 exit(-1);
508 break;
509 }
510 }
511
512 registerSigHandler();
513
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700514 bool ok = startTrace(isRoot);
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800515
516 if (ok) {
517 printf("capturing trace...");
518 fflush(stdout);
519
520 // We clear the trace after starting it because tracing gets enabled for
521 // each CPU individually in the kernel. Having the beginning of the trace
522 // contain entries from only one CPU can cause "begin" entries without a
523 // matching "end" entry to show up if a task gets migrated from one CPU to
524 // another.
525 ok = clearTrace();
526
527 if (ok) {
528 // Sleep to allow the trace to be captured.
529 struct timespec timeLeft;
530 timeLeft.tv_sec = g_traceDurationSeconds;
531 timeLeft.tv_nsec = 0;
532 do {
533 if (g_traceAborted) {
534 break;
535 }
536 } while (nanosleep(&timeLeft, &timeLeft) == -1 && errno == EINTR);
537 }
538 }
539
540 // Stop the trace and restore the default settings.
Jamie Gennis4b23eef2012-06-07 16:27:03 -0700541 stopTrace(isRoot);
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800542
543 if (ok) {
544 if (!g_traceAborted) {
545 printf(" done\nTRACE:\n");
546 fflush(stdout);
547 dumpTrace();
548 } else {
549 printf("\ntrace aborted.\n");
550 fflush(stdout);
551 }
552 clearTrace();
553 } else {
554 fprintf(stderr, "unable to start tracing\n");
555 }
556
Jamie Genniscc24c8e2012-03-05 19:10:37 -0800557 // Reset the trace buffer size to 1.
558 setTraceBufferSizeKB(1);
559
Jamie Gennisfb31ba62012-02-23 14:16:05 -0800560 return g_traceAborted ? 1 : 0;
561}