15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event_impl.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/base_switches.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/leak_annotations.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event.h"
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/debug/trace_event_synthetic_delay.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/float_util.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/format_macros.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/json/string_escape.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h"
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "base/message_loop/message_loop.h"
2158e6fbe4ee35d65e14b626c557d37565bf8ad179Ben Murdoch#include "base/process/process_metrics.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
265e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
275e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
28868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/cancellation_flag.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_info.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread_id_name_manager.h"
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/debug/trace_event_win.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeleteTraceLogForTesting {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static void Delete() {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Singleton<base::debug::TraceLog,
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch              LeakySingletonTraits<base::debug::TraceLog> >::OnExit(0);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The thread buckets for the sampling profiler.
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochBASE_EXPORT TRACE_EVENT_API_ATOMIC_WORD g_trace_state[3];
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace debug {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)namespace {
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// The overhead of TraceEvent above this threshold will be reported in the
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// trace.
5958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)const int kOverheadReportThresholdInMicroseconds = 50;
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// String options that can be used to initialize TraceOptions.
625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kRecordUntilFull[] = "record-until-full";
635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kRecordContinuously[] = "record-continuously";
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const char kRecordAsMuchAsPossible[] = "record-as-much-as-possible";
655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kTraceToConsole[] = "trace-to-console";
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kEnableSampling[] = "enable-sampling";
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)const char kEnableSystrace[] = "enable-systrace";
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Controls the number of trace events we will buffer in-memory
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// before throwing them away.
714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kTraceBufferChunkSize = TraceBufferChunk::kTraceBufferChunkSize;
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const size_t kTraceEventVectorBigBufferChunks =
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    512000000 / kTraceBufferChunkSize;
744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kTraceEventVectorBufferChunks = 256000 / kTraceBufferChunkSize;
754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kTraceEventRingBufferChunks = kTraceEventVectorBufferChunks / 4;
764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kTraceEventBatchChunks = 1000 / kTraceBufferChunkSize;
774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Can store results for 30 seconds with 1 ms sampling interval.
784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const size_t kMonitorTraceEventBufferChunks = 30000 / kTraceBufferChunkSize;
791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// ECHO_TO_CONSOLE needs a small buffer to hold the unfinished COMPLETE events.
801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const size_t kEchoToConsoleTraceEventBufferChunks = 256;
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kThreadFlushTimeoutMs = 3000;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if !defined(OS_NACL)
85a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575.
86a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const char kEchoToConsoleCategoryFilter[] = "-ipc,-task";
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
88a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY(";
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#define MAX_CATEGORY_GROUPS 100
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Parallel arrays g_category_groups and g_category_group_enabled are separate
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// so that a pointer to a member of g_category_group_enabled can be easily
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// converted to an index into g_category_groups. This allows macros to deal
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// only with char enabled pointers from g_category_group_enabled, and we can
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// convert internally to determine the category name from the char enabled
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// pointer.
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* g_category_groups[MAX_CATEGORY_GROUPS] = {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  "toplevel",
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "tracing already shutdown",
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  "tracing categories exhausted; must increase MAX_CATEGORY_GROUPS",
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "__metadata",
10458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // For reporting trace_event overhead. For thread local event buffers only.
10558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  "trace_event_overhead"};
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The enabled flag is char instead of bool so that the API can be used from C.
108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 };
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Indexes here have to match the g_category_groups array indexes above.
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int g_category_already_shutdown = 1;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int g_category_categories_exhausted = 2;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int g_category_metadata = 3;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int g_category_trace_event_overhead = 4;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const int g_num_builtin_categories = 5;
115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Skip default categories.
116a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbase::subtle::AtomicWord g_category_index = g_num_builtin_categories;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The name of the current thread. This is used to decide if the current
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// thread name has changed. We combine all the seen thread names into the
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// output name for the thread.
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LazyInstance<ThreadLocalPointer<const char> >::Leaky
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_current_thread_name = LAZY_INSTANCE_INITIALIZER;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TimeTicks ThreadNow() {
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return TimeTicks::IsThreadNowSupported() ?
12658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      TimeTicks::ThreadNow() : TimeTicks();
12758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class TraceBufferRingBuffer : public TraceBuffer {
1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TraceBufferRingBuffer(size_t max_chunks)
1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : max_chunks_(max_chunks),
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        recyclable_chunks_queue_(new size_t[queue_capacity()]),
1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        queue_head_(0),
1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        queue_tail_(max_chunks),
1364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        current_iteration_index_(0),
1374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        current_chunk_seq_(1) {
1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    chunks_.reserve(max_chunks);
1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < max_chunks; ++i)
1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      recyclable_chunks_queue_[i] = i;
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t* index) OVERRIDE {
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // Because the number of threads is much less than the number of chunks,
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // the queue should never be empty.
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(!QueueIsEmpty());
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *index = recyclable_chunks_queue_[queue_head_];
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    queue_head_ = NextQueueIndex(queue_head_);
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    current_iteration_index_ = queue_head_;
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (*index >= chunks_.size())
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      chunks_.resize(*index + 1);
1544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    TraceBufferChunk* chunk = chunks_[*index];
1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    chunks_[*index] = NULL;  // Put NULL in the slot of a in-flight chunk.
1574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (chunk)
1584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      chunk->Reset(current_chunk_seq_++);
1594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    else
1604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      chunk = new TraceBufferChunk(current_chunk_seq_++);
1614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return scoped_ptr<TraceBufferChunk>(chunk);
1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
1644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void ReturnChunk(size_t index,
1664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           scoped_ptr<TraceBufferChunk> chunk) OVERRIDE {
1674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // When this method is called, the queue should not be full because it
1684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // can contain all chunks including the one to be returned.
1694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(!QueueIsFull());
1704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(chunk);
1714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK_LT(index, chunks_.size());
1724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(!chunks_[index]);
1734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    chunks_[index] = chunk.release();
1744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    recyclable_chunks_queue_[queue_tail_] = index;
1754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    queue_tail_ = NextQueueIndex(queue_tail_);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual bool IsFull() const OVERRIDE {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual size_t Size() const OVERRIDE {
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // This is approximate because not all of the chunks are full.
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return chunks_.size() * kTraceBufferChunkSize;
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual size_t Capacity() const OVERRIDE {
1884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return max_chunks_ * kTraceBufferChunkSize;
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) OVERRIDE {
1928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (handle.chunk_index >= chunks_.size())
1938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return NULL;
1948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    TraceBufferChunk* chunk = chunks_[handle.chunk_index];
1958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!chunk || chunk->seq() != handle.chunk_seq)
1968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return NULL;
1978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return chunk->GetEventAt(handle.event_index);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual const TraceBufferChunk* NextChunk() OVERRIDE {
2014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (chunks_.empty())
2024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return NULL;
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    while (current_iteration_index_ != queue_tail_) {
2054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      size_t chunk_index = recyclable_chunks_queue_[current_iteration_index_];
2064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      current_iteration_index_ = NextQueueIndex(current_iteration_index_);
2074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (chunk_index >= chunks_.size()) // Skip uninitialized chunks.
2084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        continue;
2094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      DCHECK(chunks_[chunk_index]);
2104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return chunks_[chunk_index];
2114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual scoped_ptr<TraceBuffer> CloneForIteration() const OVERRIDE {
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<ClonedTraceBuffer> cloned_buffer(new ClonedTraceBuffer());
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t queue_index = queue_head_; queue_index != queue_tail_;
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        queue_index = NextQueueIndex(queue_index)) {
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      size_t chunk_index = recyclable_chunks_queue_[queue_index];
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (chunk_index >= chunks_.size()) // Skip uninitialized chunks.
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        continue;
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      TraceBufferChunk* chunk = chunks_[chunk_index];
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      cloned_buffer->chunks_.push_back(chunk ? chunk->Clone().release() : NULL);
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return cloned_buffer.PassAs<TraceBuffer>();
2263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
2291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  class ClonedTraceBuffer : public TraceBuffer {
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)   public:
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ClonedTraceBuffer() : current_iteration_index_(0) {}
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // The only implemented method.
2344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    virtual const TraceBufferChunk* NextChunk() OVERRIDE {
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return current_iteration_index_ < chunks_.size() ?
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          chunks_[current_iteration_index_++] : NULL;
2374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t* index) OVERRIDE {
2401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      NOTIMPLEMENTED();
2411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return scoped_ptr<TraceBufferChunk>();
2421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    virtual void ReturnChunk(size_t index,
2441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                             scoped_ptr<TraceBufferChunk>) OVERRIDE {
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      NOTIMPLEMENTED();
2461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    virtual bool IsFull() const OVERRIDE { return false; }
2481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    virtual size_t Size() const OVERRIDE { return 0; }
2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    virtual size_t Capacity() const OVERRIDE { return 0; }
2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) OVERRIDE {
2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return NULL;
2521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    virtual scoped_ptr<TraceBuffer> CloneForIteration() const OVERRIDE {
2541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      NOTIMPLEMENTED();
2551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return scoped_ptr<TraceBuffer>();
2561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
2571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    size_t current_iteration_index_;
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ScopedVector<TraceBufferChunk> chunks_;
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  };
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool QueueIsEmpty() const {
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return queue_head_ == queue_tail_;
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t QueueSize() const {
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return queue_tail_ > queue_head_ ? queue_tail_ - queue_head_ :
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        queue_tail_ + queue_capacity() - queue_head_;
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool QueueIsFull() const {
2724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return QueueSize() == queue_capacity() - 1;
2734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t queue_capacity() const {
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // One extra space to help distinguish full state and empty state.
2774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return max_chunks_ + 1;
2784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t NextQueueIndex(size_t index) const {
2813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    index++;
2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (index >= queue_capacity())
2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      index = 0;
2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return index;
2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
2863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
2874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t max_chunks_;
2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedVector<TraceBufferChunk> chunks_;
2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<size_t[]> recyclable_chunks_queue_;
2914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t queue_head_;
2924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t queue_tail_;
2934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t current_iteration_index_;
2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  uint32 current_chunk_seq_;
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TraceBufferRingBuffer);
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TraceBufferVector : public TraceBuffer {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TraceBufferVector(size_t max_chunks)
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : in_flight_chunk_count_(0),
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        current_iteration_index_(0),
3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        max_chunks_(max_chunks) {
3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    chunks_.reserve(max_chunks_);
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual scoped_ptr<TraceBufferChunk> GetChunk(size_t* index) OVERRIDE {
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // This function may be called when adding normal events or indirectly from
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // AddMetadataEventsWhileLocked(). We can not DECHECK(!IsFull()) because we
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // have to add the metadata events and flush thread-local buffers even if
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // the buffer is full.
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    *index = chunks_.size();
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    chunks_.push_back(NULL);  // Put NULL in the slot of a in-flight chunk.
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ++in_flight_chunk_count_;
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // + 1 because zero chunk_seq is not allowed.
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return scoped_ptr<TraceBufferChunk>(
3194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        new TraceBufferChunk(static_cast<uint32>(*index) + 1));
3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual void ReturnChunk(size_t index,
3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                           scoped_ptr<TraceBufferChunk> chunk) OVERRIDE {
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK_GT(in_flight_chunk_count_, 0u);
3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK_LT(index, chunks_.size());
3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    DCHECK(!chunks_[index]);
3274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    --in_flight_chunk_count_;
3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    chunks_[index] = chunk.release();
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual bool IsFull() const OVERRIDE {
3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return chunks_.size() >= max_chunks_;
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual size_t Size() const OVERRIDE {
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // This is approximate because not all of the chunks are full.
3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return chunks_.size() * kTraceBufferChunkSize;
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual size_t Capacity() const OVERRIDE {
3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    return max_chunks_ * kTraceBufferChunkSize;
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  virtual TraceEvent* GetEventByHandle(TraceEventHandle handle) OVERRIDE {
3458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (handle.chunk_index >= chunks_.size())
3468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return NULL;
3478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    TraceBufferChunk* chunk = chunks_[handle.chunk_index];
3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!chunk || chunk->seq() != handle.chunk_seq)
3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return NULL;
3508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return chunk->GetEventAt(handle.event_index);
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual const TraceBufferChunk* NextChunk() OVERRIDE {
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    while (current_iteration_index_ < chunks_.size()) {
3554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Skip in-flight chunks.
3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const TraceBufferChunk* chunk = chunks_[current_iteration_index_++];
3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (chunk)
3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        return chunk;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  virtual scoped_ptr<TraceBuffer> CloneForIteration() const OVERRIDE {
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    NOTIMPLEMENTED();
3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return scoped_ptr<TraceBuffer>();
3663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
3673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t in_flight_chunk_count_;
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t current_iteration_index_;
3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t max_chunks_;
3724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ScopedVector<TraceBufferChunk> chunks_;
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(TraceBufferVector);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)template <typename T>
3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void InitializeMetadataEvent(TraceEvent* trace_event,
3794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             int thread_id,
3804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             const char* metadata_name, const char* arg_name,
3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             const T& value) {
3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!trace_event)
3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int num_args = 1;
3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  unsigned char arg_type;
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  unsigned long long arg_value;
3884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ::trace_event_internal::SetTraceValue(value, &arg_type, &arg_value);
3894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  trace_event->Initialize(thread_id,
3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          TimeTicks(), TimeTicks(), TRACE_EVENT_PHASE_METADATA,
3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          &g_category_group_enabled[g_category_metadata],
3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          metadata_name, ::trace_event_internal::kNoEventId,
3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          num_args, &arg_name, &arg_type, &arg_value, NULL,
3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          TRACE_EVENT_FLAG_NONE);
3954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class AutoThreadLocalBoolean {
398a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) public:
399a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit AutoThreadLocalBoolean(ThreadLocalBoolean* thread_local_boolean)
400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : thread_local_boolean_(thread_local_boolean) {
401a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(!thread_local_boolean_->Get());
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    thread_local_boolean_->Set(true);
403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ~AutoThreadLocalBoolean() {
405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    thread_local_boolean_->Set(false);
406a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
407a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
408a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) private:
409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ThreadLocalBoolean* thread_local_boolean_;
410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(AutoThreadLocalBoolean);
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
4138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}  // namespace
4148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void TraceBufferChunk::Reset(uint32 new_seq) {
4168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (size_t i = 0; i < next_free_; ++i)
4178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    chunk_[i].Reset();
4188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  next_free_ = 0;
4198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  seq_ = new_seq;
4208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TraceEvent* TraceBufferChunk::AddTraceEvent(size_t* event_index) {
4238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(!IsFull());
4248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  *event_index = next_free_++;
4258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return &chunk_[*event_index];
4268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)scoped_ptr<TraceBufferChunk> TraceBufferChunk::Clone() const {
4298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  scoped_ptr<TraceBufferChunk> cloned_chunk(new TraceBufferChunk(seq_));
4308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  cloned_chunk->next_free_ = next_free_;
4318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (size_t i = 0; i < next_free_; ++i)
4328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    cloned_chunk->chunk_[i].CopyFrom(chunk_[i]);
4338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return cloned_chunk.Pass();
4348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
4358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
4364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// A helper class that allows the lock to be acquired in the middle of the scope
4374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// and unlocks at the end of scope if locked.
4388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class TraceLog::OptionalAutoLock {
4394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) public:
4404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  explicit OptionalAutoLock(Lock& lock)
4414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      : lock_(lock),
4424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        locked_(false) {
443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ~OptionalAutoLock() {
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (locked_)
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      lock_.Release();
448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void EnsureAcquired() {
4514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (!locked_) {
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      lock_.Acquire();
4534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      locked_ = true;
4544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
4564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) private:
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  Lock& lock_;
4594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool locked_;
4604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(OptionalAutoLock);
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)};
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
4631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Use this function instead of TraceEventHandle constructor to keep the
4641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// overhead of ScopedTracer (trace_event.h) constructor minimum.
4651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void MakeHandle(uint32 chunk_seq, size_t chunk_index, size_t event_index,
4661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                TraceEventHandle* handle) {
4671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(chunk_seq);
4681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(chunk_index < (1u << 16));
4691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(event_index < (1u << 16));
4701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  handle->chunk_seq = chunk_seq;
4711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  handle->chunk_index = static_cast<uint16>(chunk_index);
4721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  handle->event_index = static_cast<uint16>(event_index);
4731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
4741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceEvent
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t GetAllocLength(const char* str) { return str ? strlen(str) + 1 : 0; }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copies |*member| into |*buffer|, sets |*member| to point to this new
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// location, and then advances |*buffer| by the amount written.
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CopyTraceEventParameter(char** buffer,
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const char** member,
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const char* end) {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*member) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t written = strlcpy(*buffer, *member, end - *buffer) + 1;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LE(static_cast<int>(written), end - *buffer);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *member = *buffer;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *buffer += written;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceEvent::TraceEvent()
5018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    : duration_(TimeDelta::FromInternalValue(-1)),
5028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      id_(0u),
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      category_group_enabled_(NULL),
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_(NULL),
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_id_(0),
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      phase_(TRACE_EVENT_PHASE_BEGIN),
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      flags_(0) {
5084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (int i = 0; i < kTraceMaxNumArgs; ++i)
5094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    arg_names_[i] = NULL;
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(arg_values_, 0, sizeof(arg_values_));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TraceEvent::~TraceEvent() {
5144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceEvent::CopyFrom(const TraceEvent& other) {
5174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  timestamp_ = other.timestamp_;
5184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  thread_timestamp_ = other.thread_timestamp_;
5198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  duration_ = other.duration_;
5204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  id_ = other.id_;
5214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  category_group_enabled_ = other.category_group_enabled_;
5224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  name_ = other.name_;
5234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  thread_id_ = other.thread_id_;
5244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  phase_ = other.phase_;
5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  flags_ = other.flags_;
5264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  parameter_copy_storage_ = other.parameter_copy_storage_;
5274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (int i = 0; i < kTraceMaxNumArgs; ++i) {
5294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    arg_names_[i] = other.arg_names_[i];
5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    arg_types_[i] = other.arg_types_[i];
5314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    arg_values_[i] = other.arg_values_[i];
5324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    convertable_values_[i] = other.convertable_values_[i];
5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
5344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
5354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
5364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceEvent::Initialize(
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int thread_id,
538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    TimeTicks timestamp,
5393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    TimeTicks thread_timestamp,
540c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    char phase,
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned char* category_group_enabled,
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char* name,
543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned long long id,
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int num_args,
545c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char** arg_names,
546c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned char* arg_types,
547c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned long long* arg_values,
5484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const scoped_refptr<ConvertableToTraceFormat>* convertable_values,
5494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    unsigned char flags) {
5504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  timestamp_ = timestamp;
5514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  thread_timestamp_ = thread_timestamp;
5528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  duration_ = TimeDelta::FromInternalValue(-1);
5534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  id_ = id;
5544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  category_group_enabled_ = category_group_enabled;
5554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  name_ = name;
5564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  thread_id_ = thread_id;
5574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  phase_ = phase;
5584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  flags_ = flags;
5593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clamp num_args since it may have been set by a third_party library.
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  num_args = (num_args > kTraceMaxNumArgs) ? kTraceMaxNumArgs : num_args;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int i = 0;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; i < num_args; ++i) {
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg_names_[i] = arg_names[i];
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg_types_[i] = arg_types[i];
566c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE)
5684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      convertable_values_[i] = convertable_values[i];
569c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      arg_values_[i].as_uint = arg_values[i];
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; i < kTraceMaxNumArgs; ++i) {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg_names_[i] = NULL;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg_values_[i].as_uint = 0u;
5754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    convertable_values_[i] = NULL;
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg_types_[i] = TRACE_VALUE_TYPE_UINT;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool copy = !!(flags & TRACE_EVENT_FLAG_COPY);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t alloc_size = 0;
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (copy) {
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    alloc_size += GetAllocLength(name);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_args; ++i) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alloc_size += GetAllocLength(arg_names_[i]);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (arg_types_[i] == TRACE_VALUE_TYPE_STRING)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        arg_types_[i] = TRACE_VALUE_TYPE_COPY_STRING;
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool arg_is_copy[kTraceMaxNumArgs];
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (i = 0; i < num_args; ++i) {
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // No copying of convertable types, we retain ownership.
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only take a copy of arg_vals if they are of type COPY_STRING.
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    arg_is_copy[i] = (arg_types_[i] == TRACE_VALUE_TYPE_COPY_STRING);
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (arg_is_copy[i])
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alloc_size += GetAllocLength(arg_values_[i].as_string);
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (alloc_size) {
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parameter_copy_storage_ = new RefCountedString;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    parameter_copy_storage_->data().resize(alloc_size);
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    char* ptr = string_as_array(&parameter_copy_storage_->data());
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* end = ptr + alloc_size;
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (copy) {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CopyTraceEventParameter(&ptr, &name_, end);
609c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      for (i = 0; i < num_args; ++i) {
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CopyTraceEventParameter(&ptr, &arg_names_[i], end);
611c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (i = 0; i < num_args; ++i) {
614c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
615c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        continue;
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (arg_is_copy[i])
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CopyTraceEventParameter(&ptr, &arg_values_[i].as_string, end);
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(end, ptr) << "Overrun by " << ptr - end;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceEvent::Reset() {
6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Only reset fields that won't be initialized in Initialize(), or that may
6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // hold references to other objects.
6268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  duration_ = TimeDelta::FromInternalValue(-1);
6274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  parameter_copy_storage_ = NULL;
6284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (int i = 0; i < kTraceMaxNumArgs; ++i)
6294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    convertable_values_[i] = NULL;
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TraceEvent::UpdateDuration(const TimeTicks& now,
633f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                const TimeTicks& thread_now) {
6340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  DCHECK(duration_.ToInternalValue() == -1);
6350f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  duration_ = now - timestamp_;
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  thread_duration_ = thread_now - thread_timestamp_;
6370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
6380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceEvent::AppendValueAsJSON(unsigned char type,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   TraceEvent::TraceValue value,
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   std::string* out) {
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TRACE_VALUE_TYPE_BOOL:
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out += value.as_bool ? "true" : "false";
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TRACE_VALUE_TYPE_UINT:
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StringAppendF(out, "%" PRIu64, static_cast<uint64>(value.as_uint));
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TRACE_VALUE_TYPE_INT:
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StringAppendF(out, "%" PRId64, static_cast<int64>(value.as_int));
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    case TRACE_VALUE_TYPE_DOUBLE: {
6544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // FIXME: base/json/json_writer.cc is using the same code,
6554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      //        should be made into a common method.
6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string real;
6575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      double val = value.as_double;
6585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (IsFinite(val)) {
6595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        real = DoubleToString(val);
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Ensure that the number has a .0 if there's no decimal or 'e'.  This
6615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // makes sure that when we read the JSON back, it's interpreted as a
6625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // real rather than an int.
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (real.find('.') == std::string::npos &&
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            real.find('e') == std::string::npos &&
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            real.find('E') == std::string::npos) {
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          real.append(".0");
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
6685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // The JSON spec requires that non-integer values in the range (-1,1)
6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // have a zero before the decimal point - ".52" is not valid, "0.52" is.
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (real[0] == '.') {
6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          real.insert(0, "0");
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // "-.1" bad "-0.1" good
6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          real.insert(1, "0");
6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (IsNaN(val)){
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // The JSON spec doesn't allow NaN and Infinity (since these are
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // objects in EcmaScript).  Use strings instead.
6795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        real = "\"NaN\"";
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (val < 0) {
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        real = "\"-Infinity\"";
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else {
6835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        real = "\"Infinity\"";
6844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
6854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      StringAppendF(out, "%s", real.c_str());
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TRACE_VALUE_TYPE_POINTER:
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // JSON only supports double and int numbers.
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // So as not to lose bits from a 64-bit pointer, output as a hex string.
691c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StringAppendF(out, "\"0x%" PRIx64 "\"", static_cast<uint64>(
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     reinterpret_cast<intptr_t>(
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     value.as_pointer)));
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TRACE_VALUE_TYPE_STRING:
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TRACE_VALUE_TYPE_COPY_STRING:
6975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      EscapeJSONString(value.as_string ? value.as_string : "NULL", true, out);
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Don't know how to print this value";
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceEvent::AppendAsJSON(std::string* out) const {
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 time_int64 = timestamp_.ToInternalValue();
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int process_id = TraceLog::GetInstance()->process_id();
708c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Category group checked at category creation time.
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!strchr(name_, '"'));
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringAppendF(out,
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "{\"cat\":\"%s\",\"pid\":%i,\"tid\":%i,\"ts\":%" PRId64 ","
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "\"ph\":\"%c\",\"name\":\"%s\",\"args\":{",
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TraceLog::GetCategoryGroupName(category_group_enabled_),
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      process_id,
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      thread_id_,
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      time_int64,
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      phase_,
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_);
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Output argument names and values, stop at first NULL argument name.
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i > 0)
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *out += ",";
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out += "\"";
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out += arg_names_[i];
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *out += "\":";
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
728c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
729c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      convertable_values_[i]->AppendAsTraceFormat(out);
730c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    else
731c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      AppendValueAsJSON(arg_types_[i], arg_values_[i], out);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out += "}";
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (phase_ == TRACE_EVENT_PHASE_COMPLETE) {
7368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    int64 duration = duration_.ToInternalValue();
7378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (duration != -1)
7388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      StringAppendF(out, ",\"dur\":%" PRId64, duration);
739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!thread_timestamp_.is_null()) {
740f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      int64 thread_duration = thread_duration_.ToInternalValue();
741f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (thread_duration != -1)
742f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        StringAppendF(out, ",\"tdur\":%" PRId64, thread_duration);
743f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
7448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
7458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
7463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Output tts if thread_timestamp is valid.
7473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!thread_timestamp_.is_null()) {
7483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int64 thread_time_int64 = thread_timestamp_.ToInternalValue();
7493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    StringAppendF(out, ",\"tts\":%" PRId64, thread_time_int64);
7503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
7513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If id_ is set, print it out as a hex string so we don't loose any
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bits (it might be a 64-bit pointer).
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (flags_ & TRACE_EVENT_FLAG_HAS_ID)
755c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StringAppendF(out, ",\"id\":\"0x%" PRIx64 "\"", static_cast<uint64>(id_));
756c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
757c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Instant events also output their scope.
758c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (phase_ == TRACE_EVENT_PHASE_INSTANT) {
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    char scope = '?';
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    switch (flags_ & TRACE_EVENT_FLAG_SCOPE_MASK) {
761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case TRACE_EVENT_SCOPE_GLOBAL:
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        scope = TRACE_EVENT_SCOPE_NAME_GLOBAL;
763c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
764c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
765c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case TRACE_EVENT_SCOPE_PROCESS:
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        scope = TRACE_EVENT_SCOPE_NAME_PROCESS;
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      case TRACE_EVENT_SCOPE_THREAD:
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        scope = TRACE_EVENT_SCOPE_NAME_THREAD;
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        break;
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StringAppendF(out, ",\"s\":\"%c\"", scope);
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *out += "}";
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid TraceEvent::AppendPrettyPrinted(std::ostringstream* out) const {
7807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  *out << name_ << "[";
7817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  *out << TraceLog::GetCategoryGroupName(category_group_enabled_);
7827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  *out << "]";
7837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (arg_names_[0]) {
7847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    *out << ", {";
7857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for (int i = 0; i < kTraceMaxNumArgs && arg_names_[i]; ++i) {
7867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (i > 0)
7877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        *out << ", ";
7887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      *out << arg_names_[i] << ":";
7897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      std::string value_as_text;
7907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      if (arg_types_[i] == TRACE_VALUE_TYPE_CONVERTABLE)
7927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        convertable_values_[i]->AppendAsTraceFormat(&value_as_text);
7937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      else
7947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        AppendValueAsJSON(arg_types_[i], arg_values_[i], &value_as_text);
7957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
7967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      *out << value_as_text;
7977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
7987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    *out << "}";
7997dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
8007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
8017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceResultBuffer
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceResultBuffer::OutputCallback
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TraceResultBuffer::SimpleOutput::GetCallback() {
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return Bind(&SimpleOutput::Append, Unretained(this));
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceResultBuffer::SimpleOutput::Append(
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& json_trace_output) {
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  json_output += json_trace_output;
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceResultBuffer::TraceResultBuffer() : append_comma_(false) {
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceResultBuffer::~TraceResultBuffer() {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceResultBuffer::SetOutputCallback(
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const OutputCallback& json_chunk_callback) {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_callback_ = json_chunk_callback;
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceResultBuffer::Start() {
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  append_comma_ = false;
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_callback_.Run("[");
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceResultBuffer::AddFragment(const std::string& trace_fragment) {
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (append_comma_)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output_callback_.Run(",");
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  append_comma_ = true;
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_callback_.Run(trace_fragment);
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceResultBuffer::Finish() {
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output_callback_.Run("]");
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// TraceSamplingThread
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TraceBucketData;
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef base::Callback<void(TraceBucketData*)> TraceSampleCallback;
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TraceBucketData {
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TraceBucketData(base::subtle::AtomicWord* bucket,
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  const char* name,
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  TraceSampleCallback callback);
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~TraceBucketData();
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT_API_ATOMIC_WORD* bucket;
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* bucket_name;
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TraceSampleCallback callback;
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This object must be created on the IO thread.
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class TraceSamplingThread : public PlatformThread::Delegate {
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TraceSamplingThread();
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~TraceSamplingThread();
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Implementation of PlatformThread::Delegate:
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ThreadMain() OVERRIDE;
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  static void DefaultSamplingCallback(TraceBucketData* bucekt_data);
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Stop();
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  void WaitSamplingEventForTesting();
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class TraceLog;
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetSamples();
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Not thread-safe. Once the ThreadMain has been called, this can no longer
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // be called.
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void RegisterSampleBucket(TRACE_EVENT_API_ATOMIC_WORD* bucket,
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const char* const name,
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            TraceSampleCallback callback);
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Splits a combined "category\0name" into the two component parts.
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static void ExtractCategoryAndName(const char* combined,
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const char** category,
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     const char** name);
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<TraceBucketData> sample_buckets_;
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool thread_running_;
894f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  CancellationFlag cancellation_flag_;
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  WaitableEvent waitable_event_for_testing_;
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TraceSamplingThread::TraceSamplingThread()
900f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    : thread_running_(false),
901f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      waitable_event_for_testing_(false, false) {
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TraceSamplingThread::~TraceSamplingThread() {
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TraceSamplingThread::ThreadMain() {
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PlatformThread::SetName("Sampling Thread");
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_running_ = true;
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int kSamplingFrequencyMicroseconds = 1000;
911f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  while (!cancellation_flag_.IsSet()) {
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PlatformThread::Sleep(
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        TimeDelta::FromMicroseconds(kSamplingFrequencyMicroseconds));
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GetSamples();
915f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    waitable_event_for_testing_.Signal();
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
9204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceSamplingThread::DefaultSamplingCallback(
9214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    TraceBucketData* bucket_data) {
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT_API_ATOMIC_WORD category_and_name =
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      TRACE_EVENT_API_ATOMIC_LOAD(*bucket_data->bucket);
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!category_and_name)
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* const combined =
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reinterpret_cast<const char* const>(category_and_name);
928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char* category_group;
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const char* name;
930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ExtractCategoryAndName(combined, &category_group, &name);
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TRACE_EVENT_API_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_SAMPLE,
932c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      TraceLog::GetCategoryGroupEnabled(category_group),
933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      name, 0, 0, NULL, NULL, NULL, NULL, 0);
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TraceSamplingThread::GetSamples() {
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < sample_buckets_.size(); ++i) {
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TraceBucketData* bucket_data = &sample_buckets_[i];
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bucket_data->callback.Run(bucket_data);
9402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TraceSamplingThread::RegisterSampleBucket(
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TRACE_EVENT_API_ATOMIC_WORD* bucket,
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* const name,
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TraceSampleCallback callback) {
947f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Access to sample_buckets_ doesn't cause races with the sampling thread
948f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // that uses the sample_buckets_, because it is guaranteed that
949f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // RegisterSampleBucket is called before the sampling thread is created.
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!thread_running_);
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  sample_buckets_.push_back(TraceBucketData(bucket, name, callback));
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TraceSamplingThread::ExtractCategoryAndName(const char* combined,
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 const char** category,
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                 const char** name) {
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *category = combined;
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *name = &combined[strlen(combined) + 1];
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TraceSamplingThread::Stop() {
963f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  cancellation_flag_.Set();
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
966f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TraceSamplingThread::WaitSamplingEventForTesting() {
967f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  waitable_event_for_testing_.Wait();
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TraceBucketData::TraceBucketData(base::subtle::AtomicWord* bucket,
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 const char* name,
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 TraceSampleCallback callback)
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : bucket(bucket),
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bucket_name(name),
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      callback(callback) {
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TraceBucketData::~TraceBucketData() {
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// TraceOptions
9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
9876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool TraceOptions::SetFromString(const std::string& options_string) {
9886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  record_mode = RECORD_UNTIL_FULL;
9896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  enable_sampling = false;
9906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  enable_systrace = false;
9916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<std::string> split;
9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::vector<std::string>::iterator iter;
9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  base::SplitString(options_string, ',', &split);
9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  for (iter = split.begin(); iter != split.end(); ++iter) {
9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (*iter == kRecordUntilFull) {
9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      record_mode = RECORD_UNTIL_FULL;
9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (*iter == kRecordContinuously) {
9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      record_mode = RECORD_CONTINUOUSLY;
10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (*iter == kTraceToConsole) {
10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      record_mode = ECHO_TO_CONSOLE;
10026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else if (*iter == kRecordAsMuchAsPossible) {
10036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      record_mode = RECORD_AS_MUCH_AS_POSSIBLE;
10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (*iter == kEnableSampling) {
10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      enable_sampling = true;
10065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else if (*iter == kEnableSystrace) {
10075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      enable_systrace = true;
10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    } else {
10096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return false;
10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
10115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
10126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return true;
10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)std::string TraceOptions::ToString() const {
10165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  std::string ret;
10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  switch (record_mode) {
10185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case RECORD_UNTIL_FULL:
10195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ret = kRecordUntilFull;
10205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
10215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case RECORD_CONTINUOUSLY:
10225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ret = kRecordContinuously;
10235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
10245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case ECHO_TO_CONSOLE:
10255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      ret = kTraceToConsole;
10265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      break;
10276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case RECORD_AS_MUCH_AS_POSSIBLE:
10286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      ret = kRecordAsMuchAsPossible;
10296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
10305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    default:
10315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      NOTREACHED();
10325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
10335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (enable_sampling)
10345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ret = ret + "," + kEnableSampling;
10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (enable_systrace)
10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ret = ret + "," + kEnableSystrace;
10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return ret;
10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
10395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
10405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
10415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TraceLog
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
104658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)class TraceLog::ThreadLocalEventBuffer
104758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : public MessageLoop::DestructionObserver {
104858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) public:
104958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ThreadLocalEventBuffer(TraceLog* trace_log);
105058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual ~ThreadLocalEventBuffer();
105158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1052a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  TraceEvent* AddTraceEvent(TraceEventHandle* handle);
10534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
105458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  void ReportOverhead(const TimeTicks& event_timestamp,
1055a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                      const TimeTicks& event_thread_timestamp);
10564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  TraceEvent* GetEventByHandle(TraceEventHandle handle) {
10588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (!chunk_ || handle.chunk_seq != chunk_->seq() ||
10598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        handle.chunk_index != chunk_index_)
10608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      return NULL;
10618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
10628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return chunk_->GetEventAt(handle.event_index);
10634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
10644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
10654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int generation() const { return generation_; }
106658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
106758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) private:
106858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // MessageLoop::DestructionObserver
106958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual void WillDestroyCurrentMessageLoop() OVERRIDE;
107058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void FlushWhileLocked();
107258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  void CheckThisIsCurrentBuffer() const {
107458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(trace_log_->thread_local_event_buffer_.Get() == this);
107558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
107658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
107758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Since TraceLog is a leaky singleton, trace_log_ will always be valid
107858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // as long as the thread exists.
107958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TraceLog* trace_log_;
10804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<TraceBufferChunk> chunk_;
10814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t chunk_index_;
108258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  int event_count_;
108358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TimeDelta overhead_;
10844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int generation_;
108558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
108658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ThreadLocalEventBuffer);
108758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)};
108858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
108958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TraceLog::ThreadLocalEventBuffer::ThreadLocalEventBuffer(TraceLog* trace_log)
109058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    : trace_log_(trace_log),
10914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      chunk_index_(0),
10924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      event_count_(0),
10934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      generation_(trace_log->generation()) {
109458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // ThreadLocalEventBuffer is created only if the thread has a message loop, so
109558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // the following message_loop won't be NULL.
109658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MessageLoop* message_loop = MessageLoop::current();
109758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  message_loop->AddDestructionObserver(this);
109858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
109958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  AutoLock lock(trace_log->lock_);
110058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  trace_log->thread_message_loops_.insert(message_loop);
110158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
110258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
110358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)TraceLog::ThreadLocalEventBuffer::~ThreadLocalEventBuffer() {
110458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckThisIsCurrentBuffer();
110558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  MessageLoop::current()->RemoveDestructionObserver(this);
110658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
110758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Zero event_count_ happens in either of the following cases:
110858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // - no event generated for the thread;
110958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // - the thread has no message loop;
111058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // - trace_event_overhead is disabled.
111158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (event_count_) {
1112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InitializeMetadataEvent(AddTraceEvent(NULL),
11134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            static_cast<int>(base::PlatformThread::CurrentId()),
11144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            "overhead", "average_overhead",
11154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            overhead_.InMillisecondsF() / event_count_);
11164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
11174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
111858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {
111958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    AutoLock lock(trace_log_->lock_);
11204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FlushWhileLocked();
112158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    trace_log_->thread_message_loops_.erase(MessageLoop::current());
112258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
112358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  trace_log_->thread_local_event_buffer_.Set(NULL);
112458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
112558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TraceEvent* TraceLog::ThreadLocalEventBuffer::AddTraceEvent(
11278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    TraceEventHandle* handle) {
112858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  CheckThisIsCurrentBuffer();
11294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (chunk_ && chunk_->IsFull()) {
11314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AutoLock lock(trace_log_->lock_);
11324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    FlushWhileLocked();
11334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    chunk_.reset();
11344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
11354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!chunk_) {
113658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    AutoLock lock(trace_log_->lock_);
11374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    chunk_ = trace_log_->logged_events_->GetChunk(&chunk_index_);
1138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    trace_log_->CheckIfBufferIsFullWhileLocked();
113958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
11404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!chunk_)
11414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
11424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
11438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  size_t event_index;
11448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  TraceEvent* trace_event = chunk_->AddTraceEvent(&event_index);
11458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (trace_event && handle)
11461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    MakeHandle(chunk_->seq(), chunk_index_, event_index, handle);
11471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
11488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return trace_event;
114958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
115058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
115158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TraceLog::ThreadLocalEventBuffer::ReportOverhead(
11524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const TimeTicks& event_timestamp,
1153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const TimeTicks& event_thread_timestamp) {
115458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!g_category_group_enabled[g_category_trace_event_overhead])
115558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
115658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  CheckThisIsCurrentBuffer();
11584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
115958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  event_count_++;
1160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TimeTicks thread_now = ThreadNow();
11610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  TimeTicks now = trace_log_->OffsetNow();
116258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TimeDelta overhead = now - event_timestamp;
116358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (overhead.InMicroseconds() >= kOverheadReportThresholdInMicroseconds) {
1164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TraceEvent* trace_event = AddTraceEvent(NULL);
11654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (trace_event) {
11664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      trace_event->Initialize(
11678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          static_cast<int>(PlatformThread::CurrentId()),
11688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          event_timestamp, event_thread_timestamp,
11698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          TRACE_EVENT_PHASE_COMPLETE,
11704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          &g_category_group_enabled[g_category_trace_event_overhead],
11714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          "overhead", 0, 0, NULL, NULL, NULL, NULL, 0);
1172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      trace_event->UpdateDuration(now, thread_now);
11734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
117458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
117558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  overhead_ += overhead;
117658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
117758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
117858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void TraceLog::ThreadLocalEventBuffer::WillDestroyCurrentMessageLoop() {
117958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  delete this;
118058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
118158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceLog::ThreadLocalEventBuffer::FlushWhileLocked() {
11831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!chunk_)
11841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
11851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
118658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  trace_log_->lock_.AssertAcquired();
11871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (trace_log_->CheckGeneration(generation_)) {
11885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Return the chunk to the buffer only if the generation matches.
11891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    trace_log_->logged_events_->ReturnChunk(chunk_index_, chunk_.Pass());
11901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
11911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // Otherwise this method may be called from the destructor, or TraceLog will
11921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // find the generation mismatch and delete this buffer soon.
119358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
119458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceLog* TraceLog::GetInstance() {
11977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return Singleton<TraceLog, LeakySingletonTraits<TraceLog> >::get();
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceLog::TraceLog()
12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    : mode_(DISABLED),
1202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      num_traces_recorded_(0),
120358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      event_callback_(0),
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dispatching_to_observer_list_(false),
12057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      process_sort_index_(0),
120658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      process_id_hash_(0),
120758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      process_id_(0),
120858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      watch_category_(0),
12095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      trace_options_(kInternalRecordUntilFull),
1210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      sampling_thread_handle_(0),
121158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      category_filter_(CategoryFilter::kDefaultCategoryFilterString),
1212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event_callback_category_filter_(
1213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          CategoryFilter::kDefaultCategoryFilterString),
12144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      thread_shared_chunk_index_(0),
12154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      generation_(0) {
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trace is enabled or disabled on one thread while other threads are
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // accessing the enabled flag. We don't care whether edge-case events are
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // traced or not, so we allow races on the enabled flag to keep the trace
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // macros fast.
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(jbates): ANNOTATE_BENIGN_RACE_SIZED crashes windows TSAN bots:
1221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // ANNOTATE_BENIGN_RACE_SIZED(g_category_group_enabled,
1222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //                            sizeof(g_category_group_enabled),
1223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //                           "trace_event category enabled");
1224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (int i = 0; i < MAX_CATEGORY_GROUPS; ++i) {
1225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ANNOTATE_BENIGN_RACE(&g_category_group_enabled[i],
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         "trace_event category enabled");
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_NACL)  // NaCl shouldn't expose the process id.
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SetProcessID(0);
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetProcessID(static_cast<int>(GetCurrentProcId()));
12327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
12337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // NaCl also shouldn't access the command line.
12347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (CommandLine::InitializedForCurrentProcess() &&
12357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CommandLine::ForCurrentProcess()->HasSwitch(switches::kTraceToConsole)) {
12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string filter = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
12375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        switches::kTraceToConsole);
12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (filter.empty()) {
12395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      filter = kEchoToConsoleCategoryFilter;
12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      filter.append(",");
12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      filter.append(kEchoToConsoleCategoryFilter);
12435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "Start " << switches::kTraceToConsole
12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               << " with CategoryFilter '" << filter << "'.";
12475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    SetEnabled(CategoryFilter(filter),
12485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               RECORDING_MODE,
12495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)               TraceOptions(ECHO_TO_CONSOLE));
12507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  logged_events_.reset(CreateTraceBuffer());
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TraceLog::~TraceLog() {
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const unsigned char* TraceLog::GetCategoryGroupEnabled(
1260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char* category_group) {
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TraceLog* tracelog = GetInstance();
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tracelog) {
1263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(!g_category_group_enabled[g_category_already_shutdown]);
1264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return &g_category_group_enabled[g_category_already_shutdown];
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return tracelog->GetCategoryGroupEnabledInternal(category_group);
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const char* TraceLog::GetCategoryGroupName(
1270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned char* category_group_enabled) {
1271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Calculate the index of the category group by finding
1272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // category_group_enabled in g_category_group_enabled array.
1273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uintptr_t category_begin =
1274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      reinterpret_cast<uintptr_t>(g_category_group_enabled);
1275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  uintptr_t category_ptr = reinterpret_cast<uintptr_t>(category_group_enabled);
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(category_ptr >= category_begin &&
1277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)         category_ptr < reinterpret_cast<uintptr_t>(
1278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)             g_category_group_enabled + MAX_CATEGORY_GROUPS)) <<
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "out of bounds category pointer";
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uintptr_t category_index =
1281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      (category_ptr - category_begin) / sizeof(g_category_group_enabled[0]);
1282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return g_category_groups[category_index];
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid TraceLog::UpdateCategoryGroupEnabledFlag(size_t category_index) {
1286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  unsigned char enabled_flag = 0;
1287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  const char* category_group = g_category_groups[category_index];
12885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (mode_ == RECORDING_MODE &&
12895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      category_filter_.IsCategoryGroupEnabled(category_group))
1290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    enabled_flag |= ENABLED_FOR_RECORDING;
12915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (mode_ == MONITORING_MODE &&
12925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      category_filter_.IsCategoryGroupEnabled(category_group))
12935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    enabled_flag |= ENABLED_FOR_MONITORING;
1294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (event_callback_ &&
1295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event_callback_category_filter_.IsCategoryGroupEnabled(category_group))
1296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    enabled_flag |= ENABLED_FOR_EVENT_CALLBACK;
1297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  g_category_group_enabled[category_index] = enabled_flag;
129890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
129990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1300bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdochvoid TraceLog::UpdateCategoryGroupEnabledFlags() {
1301116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t category_index = base::subtle::NoBarrier_Load(&g_category_index);
1302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < category_index; i++)
1303bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    UpdateCategoryGroupEnabledFlag(i);
1304bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
1305bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
13065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TraceLog::UpdateSyntheticDelaysFromCategoryFilter() {
13075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResetTraceEventSyntheticDelays();
13085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const CategoryFilter::StringList& delays =
13095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      category_filter_.GetSyntheticDelayValues();
13105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CategoryFilter::StringList::const_iterator ci;
13115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (ci = delays.begin(); ci != delays.end(); ++ci) {
13125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StringTokenizer tokens(*ci, ";");
13135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!tokens.GetNext())
13145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
13155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    TraceEventSyntheticDelay* delay =
13165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        TraceEventSyntheticDelay::Lookup(tokens.token());
13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    while (tokens.GetNext()) {
13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      std::string token = tokens.token();
13195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      char* duration_end;
13205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      double target_duration = strtod(token.c_str(), &duration_end);
13215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (duration_end != token.c_str()) {
13225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delay->SetTargetDuration(
13235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            TimeDelta::FromMicroseconds(target_duration * 1e6));
13245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (token == "static") {
13255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delay->SetMode(TraceEventSyntheticDelay::STATIC);
13265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (token == "oneshot") {
13275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delay->SetMode(TraceEventSyntheticDelay::ONE_SHOT);
13285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      } else if (token == "alternating") {
13295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delay->SetMode(TraceEventSyntheticDelay::ALTERNATING);
13305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
13315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
13325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
13335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
13345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const unsigned char* TraceLog::GetCategoryGroupEnabledInternal(
1336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char* category_group) {
1337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!strchr(category_group, '"')) <<
1338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      "Category groups may not contain double quote";
1339a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // The g_category_groups is append only, avoid using a lock for the fast path.
1340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t current_category_index = base::subtle::Acquire_Load(&g_category_index);
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Search for pre-existing category group.
1343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < current_category_index; ++i) {
1344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (strcmp(g_category_groups[i], category_group) == 0) {
1345a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      return &g_category_group_enabled[i];
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1349a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  unsigned char* category_group_enabled = NULL;
1350a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // This is the slow path: the lock is not held in the case above, so more
1351a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // than one thread could have reached here trying to add the same category.
1352a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Only hold to lock when actually appending a new category, and
1353a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // check the categories groups again.
1354a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  AutoLock lock(lock_);
1355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t category_index = base::subtle::Acquire_Load(&g_category_index);
1356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = 0; i < category_index; ++i) {
1357a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (strcmp(g_category_groups[i], category_group) == 0) {
1358a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      return &g_category_group_enabled[i];
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1361a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
1362a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // Create a new category group.
1363a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(category_index < MAX_CATEGORY_GROUPS) <<
1364a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      "must increase MAX_CATEGORY_GROUPS";
1365a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (category_index < MAX_CATEGORY_GROUPS) {
1366a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Don't hold on to the category_group pointer, so that we can create
1367a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // category groups with strings not known at compile time (this is
1368a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // required by SetWatchEvent).
1369a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const char* new_group = strdup(category_group);
1370a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    ANNOTATE_LEAKING_OBJECT_PTR(new_group);
1371a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    g_category_groups[category_index] = new_group;
1372a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    DCHECK(!g_category_group_enabled[category_index]);
1373a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Note that if both included and excluded patterns in the
1374a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // CategoryFilter are empty, we exclude nothing,
1375a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // thereby enabling this category group.
1376a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    UpdateCategoryGroupEnabledFlag(category_index);
1377a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    category_group_enabled = &g_category_group_enabled[category_index];
1378a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Update the max index now.
1379a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    base::subtle::Release_Store(&g_category_index, category_index + 1);
1380a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  } else {
1381a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    category_group_enabled =
1382a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        &g_category_group_enabled[g_category_categories_exhausted];
1383a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
1384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return category_group_enabled;
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1387c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TraceLog::GetKnownCategoryGroups(
1388c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::vector<std::string>* category_groups) {
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(lock_);
139058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  category_groups->push_back(
139158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      g_category_groups[g_category_trace_event_overhead]);
1392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  size_t category_index = base::subtle::NoBarrier_Load(&g_category_index);
1393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  for (size_t i = g_num_builtin_categories; i < category_index; i++)
1394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    category_groups->push_back(g_category_groups[i]);
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TraceLog::SetEnabled(const CategoryFilter& category_filter,
13985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                          Mode mode,
13995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                          const TraceOptions& options) {
14007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::vector<EnabledStateObserver*> observer_list;
14017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
14027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AutoLock lock(lock_);
14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
140458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Can't enable tracing when Flush() is in progress.
140558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(!flush_message_loop_proxy_.get());
140658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    InternalTraceOptions new_options =
14085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)        GetInternalOptionsFromTraceOptions(options);
14095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
14105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)   InternalTraceOptions old_options = trace_options();
141158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
14125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (IsEnabled()) {
14135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (new_options != old_options) {
1414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        DLOG(ERROR) << "Attempting to re-enable tracing with a different "
14157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                    << "set of options.";
14167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
14177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
14185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (mode != mode_) {
1419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        DLOG(ERROR) << "Attempting to re-enable tracing with a different mode.";
14205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
14215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      category_filter_.Merge(category_filter);
1423bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      UpdateCategoryGroupEnabledFlags();
14247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1427f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (dispatching_to_observer_list_) {
1428f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DLOG(ERROR) <<
1429f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          "Cannot manipulate TraceLog::Enabled state from an observer.";
1430f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      return;
1431f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1432f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    mode_ = mode;
1434f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (new_options != old_options) {
14365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      subtle::NoBarrier_Store(&trace_options_, new_options);
14375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      UseNextTraceBuffer();
14387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
14392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    num_traces_recorded_++;
14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    category_filter_ = CategoryFilter(category_filter);
1443bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    UpdateCategoryGroupEnabledFlags();
14445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UpdateSyntheticDelaysFromCategoryFilter();
1445868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
14465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (new_options & kInternalEnableSampling) {
14477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      sampling_thread_.reset(new TraceSamplingThread);
14487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      sampling_thread_->RegisterSampleBucket(
14497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          &g_trace_state[0],
14507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          "bucket0",
14514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          Bind(&TraceSamplingThread::DefaultSamplingCallback));
14527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      sampling_thread_->RegisterSampleBucket(
14537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          &g_trace_state[1],
14547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          "bucket1",
14554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          Bind(&TraceSamplingThread::DefaultSamplingCallback));
14567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      sampling_thread_->RegisterSampleBucket(
14577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          &g_trace_state[2],
14587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          "bucket2",
14594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          Bind(&TraceSamplingThread::DefaultSamplingCallback));
14607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!PlatformThread::Create(
14617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)            0, sampling_thread_.get(), &sampling_thread_handle_)) {
14627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        DCHECK(false) << "failed to create thread";
14637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
14647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    dispatching_to_observer_list_ = true;
14677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    observer_list = enabled_state_observer_list_;
14687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
14697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Notify observers outside the lock in case they trigger trace events.
14707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (size_t i = 0; i < observer_list.size(); ++i)
14717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    observer_list[i]->OnTraceLogEnabled();
14722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
14747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    AutoLock lock(lock_);
14757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    dispatching_to_observer_list_ = false;
14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TraceLog::InternalTraceOptions TraceLog::GetInternalOptionsFromTraceOptions(
14805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const TraceOptions& options) {
14815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  InternalTraceOptions ret =
14825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      options.enable_sampling ? kInternalEnableSampling : kInternalNone;
14835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  switch (options.record_mode) {
14845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case RECORD_UNTIL_FULL:
14855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return ret | kInternalRecordUntilFull;
14865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case RECORD_CONTINUOUSLY:
14875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return ret | kInternalRecordContinuously;
14885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    case ECHO_TO_CONSOLE:
14895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      return ret | kInternalEchoToConsole;
14906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    case RECORD_AS_MUCH_AS_POSSIBLE:
14916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      return ret | kInternalRecordAsMuchAsPossible;
14925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
14935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  NOTREACHED();
14945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return kInternalNone;
14955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
14965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
1497f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)CategoryFilter TraceLog::GetCurrentCategoryFilter() {
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(lock_);
1499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return category_filter_;
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TraceOptions TraceLog::GetCurrentTraceOptions() const {
15035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  TraceOptions ret;
15045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  InternalTraceOptions option = trace_options();
15055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  ret.enable_sampling = (option & kInternalEnableSampling) != 0;
15065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (option & kInternalRecordUntilFull)
15075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ret.record_mode = RECORD_UNTIL_FULL;
15085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else if (option & kInternalRecordContinuously)
15095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ret.record_mode = RECORD_CONTINUOUSLY;
15105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else if (option & kInternalEchoToConsole)
15115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    ret.record_mode = ECHO_TO_CONSOLE;
15126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  else if (option & kInternalRecordAsMuchAsPossible)
15136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ret.record_mode = RECORD_AS_MUCH_AS_POSSIBLE;
15145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else
15155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    NOTREACHED();
15165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return ret;
15175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
15185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::SetDisabled() {
1520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AutoLock lock(lock_);
1521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SetDisabledWhileLocked();
1522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TraceLog::SetDisabledWhileLocked() {
1525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  lock_.AssertAcquired();
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!IsEnabled())
1528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1529f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (dispatching_to_observer_list_) {
1531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DLOG(ERROR)
1532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        << "Cannot manipulate TraceLog::Enabled state from an observer.";
1533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1534a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
15357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
15365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  mode_ = DISABLED;
15377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (sampling_thread_.get()) {
1539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Stop the sampling thread.
1540a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sampling_thread_->Stop();
1541a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    lock_.Release();
1542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    PlatformThread::Join(sampling_thread_handle_);
1543a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    lock_.Acquire();
1544a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sampling_thread_handle_ = PlatformThreadHandle();
1545a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sampling_thread_.reset();
15462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
15472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1548a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  category_filter_.Clear();
1549a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  subtle::NoBarrier_Store(&watch_category_, 0);
1550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  watch_event_name_ = "";
1551a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  UpdateCategoryGroupEnabledFlags();
1552a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AddMetadataEventsWhileLocked();
1553a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1554a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  dispatching_to_observer_list_ = true;
1555a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::vector<EnabledStateObserver*> observer_list =
1556a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      enabled_state_observer_list_;
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  {
1559a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // Dispatch to observers outside the lock in case the observer triggers a
1560a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // trace event.
1561a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    AutoUnlock unlock(lock_);
1562a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    for (size_t i = 0; i < observer_list.size(); ++i)
1563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      observer_list[i]->OnTraceLogDisabled();
15647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1565a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  dispatching_to_observer_list_ = false;
15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)int TraceLog::GetNumTracesRecorded() {
1569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AutoLock lock(lock_);
15705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!IsEnabled())
1571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return -1;
1572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return num_traces_recorded_;
1573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
15757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void TraceLog::AddEnabledStateObserver(EnabledStateObserver* listener) {
15767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  enabled_state_observer_list_.push_back(listener);
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void TraceLog::RemoveEnabledStateObserver(EnabledStateObserver* listener) {
15807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::vector<EnabledStateObserver*>::iterator it =
15817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      std::find(enabled_state_observer_list_.begin(),
15827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                enabled_state_observer_list_.end(),
15837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                listener);
15847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (it != enabled_state_observer_list_.end())
15857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    enabled_state_observer_list_.erase(it);
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1588bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochbool TraceLog::HasEnabledStateObserver(EnabledStateObserver* listener) const {
1589bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  std::vector<EnabledStateObserver*>::const_iterator it =
1590bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      std::find(enabled_state_observer_list_.begin(),
1591bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                enabled_state_observer_list_.end(),
1592bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                listener);
1593bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  return it != enabled_state_observer_list_.end();
1594bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
1595bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)float TraceLog::GetBufferPercentFull() const {
1597a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AutoLock lock(lock_);
15983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return static_cast<float>(static_cast<double>(logged_events_->Size()) /
15993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                            logged_events_->Capacity());
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1602a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool TraceLog::BufferIsFull() const {
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(lock_);
1604a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return logged_events_->IsFull();
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TraceBuffer* TraceLog::CreateTraceBuffer() {
16085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  InternalTraceOptions options = trace_options();
16095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (options & kInternalRecordContinuously)
16104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return new TraceBufferRingBuffer(kTraceEventRingBufferChunks);
16115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else if ((options & kInternalEnableSampling) && mode_ == MONITORING_MODE)
16124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return new TraceBufferRingBuffer(kMonitorTraceEventBufferChunks);
16135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  else if (options & kInternalEchoToConsole)
16141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return new TraceBufferRingBuffer(kEchoToConsoleTraceEventBufferChunks);
16156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  else if (options & kInternalRecordAsMuchAsPossible)
16166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return CreateTraceBufferVectorOfSize(kTraceEventVectorBigBufferChunks);
16175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return CreateTraceBufferVectorOfSize(kTraceEventVectorBufferChunks);
16185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
16195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
16205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)TraceBuffer* TraceLog::CreateTraceBufferVectorOfSize(size_t max_chunks) {
16215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return new TraceBufferVector(max_chunks);
16222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
16232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TraceEvent* TraceLog::AddEventToThreadSharedChunkWhileLocked(
1625a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TraceEventHandle* handle, bool check_buffer_is_full) {
162658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  lock_.AssertAcquired();
16274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
16284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (thread_shared_chunk_ && thread_shared_chunk_->IsFull()) {
16294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    logged_events_->ReturnChunk(thread_shared_chunk_index_,
16304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                thread_shared_chunk_.Pass());
16314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
16324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
16334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!thread_shared_chunk_) {
16344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread_shared_chunk_ = logged_events_->GetChunk(
16354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        &thread_shared_chunk_index_);
1636a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (check_buffer_is_full)
1637a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      CheckIfBufferIsFullWhileLocked();
16384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
16394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!thread_shared_chunk_)
16404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return NULL;
16414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
16428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  size_t event_index;
16438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  TraceEvent* trace_event = thread_shared_chunk_->AddTraceEvent(&event_index);
16448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (trace_event && handle) {
16451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    MakeHandle(thread_shared_chunk_->seq(), thread_shared_chunk_index_,
16461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)               event_index, handle);
16478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
16488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return trace_event;
164958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
165058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1651a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void TraceLog::CheckIfBufferIsFullWhileLocked() {
165258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  lock_.AssertAcquired();
16535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (logged_events_->IsFull()) {
16545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (buffer_limit_reached_timestamp_.is_null()) {
16555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      buffer_limit_reached_timestamp_ = OffsetNow();
16565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    }
1657a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    SetDisabledWhileLocked();
16585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
165958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
166058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1661f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TraceLog::SetEventCallbackEnabled(const CategoryFilter& category_filter,
1662f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                       EventCallback cb) {
1663f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AutoLock lock(lock_);
166458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  subtle::NoBarrier_Store(&event_callback_,
166558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                          reinterpret_cast<subtle::AtomicWord>(cb));
1666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  event_callback_category_filter_ = category_filter;
1667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateCategoryGroupEnabledFlags();
16682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
16692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TraceLog::SetEventCallbackDisabled() {
1671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  AutoLock lock(lock_);
1672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  subtle::NoBarrier_Store(&event_callback_, 0);
1673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UpdateCategoryGroupEnabledFlags();
1674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1675f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
167658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Flush() works as the following:
167758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 1. Flush() is called in threadA whose message loop is saved in
167858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//    flush_message_loop_proxy_;
167958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 2. If thread_message_loops_ is not empty, threadA posts task to each message
168058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//    loop to flush the thread local buffers; otherwise finish the flush;
168158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 3. FlushCurrentThread() deletes the thread local event buffer:
168258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//    - The last batch of events of the thread are flushed into the main buffer;
168358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//    - The message loop will be removed from thread_message_loops_;
168458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)//    If this is the last message loop, finish the flush;
168558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// 4. If any thread hasn't finish its flush in time, finish the flush.
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::Flush(const TraceLog::OutputCallback& cb) {
168758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (IsEnabled()) {
168858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Can't flush when tracing is enabled because otherwise PostTask would
1689f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // - generate more trace events;
1690f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // - deschedule the calling thread on some platforms causing inaccurate
169158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    //   timing of the trace events.
169258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    scoped_refptr<RefCountedString> empty_result = new RefCountedString;
169358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!cb.is_null())
169458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      cb.Run(empty_result, false);
1695d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    LOG(WARNING) << "Ignored TraceLog::Flush called when tracing is enabled";
169658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
169758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
169858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
16994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  int generation = this->generation();
17001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Copy of thread_message_loops_ to be used without locking.
17011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  std::vector<scoped_refptr<SingleThreadTaskRunner> >
17021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      thread_message_loop_task_runners;
170358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {
170458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    AutoLock lock(lock_);
170558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(!flush_message_loop_proxy_.get());
170658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    flush_message_loop_proxy_ = MessageLoopProxy::current();
170758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    DCHECK(!thread_message_loops_.size() || flush_message_loop_proxy_.get());
170858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    flush_output_callback_ = cb;
170958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (thread_shared_chunk_) {
17114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      logged_events_->ReturnChunk(thread_shared_chunk_index_,
17124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                  thread_shared_chunk_.Pass());
17134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
17144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
171558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (thread_message_loops_.size()) {
171658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      for (hash_set<MessageLoop*>::const_iterator it =
171758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)           thread_message_loops_.begin();
171858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)           it != thread_message_loops_.end(); ++it) {
17191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        thread_message_loop_task_runners.push_back((*it)->task_runner());
172058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      }
17211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
17221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
17231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
17241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (thread_message_loop_task_runners.size()) {
17251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (size_t i = 0; i < thread_message_loop_task_runners.size(); ++i) {
17261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      thread_message_loop_task_runners[i]->PostTask(
172758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          FROM_HERE,
17281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          Bind(&TraceLog::FlushCurrentThread, Unretained(this), generation));
172958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
17301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    flush_message_loop_proxy_->PostDelayedTask(
17311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
17321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        Bind(&TraceLog::OnFlushTimeout, Unretained(this), generation),
17331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        TimeDelta::FromMilliseconds(kThreadFlushTimeoutMs));
17341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
173558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
173658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FinishFlush(generation);
173858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
173958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceLog::ConvertTraceEventsToTraceFormat(
17414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    scoped_ptr<TraceBuffer> logged_events,
17424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const TraceLog::OutputCallback& flush_output_callback) {
174358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
174458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (flush_output_callback.is_null())
174558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The callback need to be called at least once even if there is no events
174858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // to let the caller know the completion of flush.
17494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  bool has_more_events = true;
175058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  do {
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<RefCountedString> json_events_str_ptr =
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new RefCountedString();
17532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    for (size_t i = 0; i < kTraceEventBatchChunks; ++i) {
17554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      const TraceBufferChunk* chunk = logged_events->NextChunk();
17564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      if (!chunk) {
17574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        has_more_events = false;
17584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        break;
17594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
17604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      for (size_t j = 0; j < chunk->size(); ++j) {
17614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        if (i > 0 || j > 0)
17624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          json_events_str_ptr->data().append(",");
17634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        chunk->GetEventAt(j)->AppendAsJSON(&(json_events_str_ptr->data()));
17644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      }
17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
176758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    flush_output_callback.Run(json_events_str_ptr, has_more_events);
176858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  } while (has_more_events);
176958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
177058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
17714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceLog::FinishFlush(int generation) {
17724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<TraceBuffer> previous_logged_events;
17734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  OutputCallback flush_output_callback;
17744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
17754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!CheckGeneration(generation))
17764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
17774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
17784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
17794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AutoLock lock(lock_);
17804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
17814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    previous_logged_events.swap(logged_events_);
17825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    UseNextTraceBuffer();
17834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread_message_loops_.clear();
17844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
17854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    flush_message_loop_proxy_ = NULL;
17864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    flush_output_callback = flush_output_callback_;
17874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    flush_output_callback_.Reset();
17884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
17894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
17904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(),
17914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                  flush_output_callback);
17924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
17934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
179458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)// Run in each thread holding a local event buffer.
17954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceLog::FlushCurrentThread(int generation) {
179658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {
179758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    AutoLock lock(lock_);
17981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!CheckGeneration(generation) || !flush_message_loop_proxy_.get()) {
179958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // This is late. The corresponding flush has finished.
180058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
180158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
180358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // This will flush the thread local buffer.
180558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  delete thread_local_event_buffer_.Get();
180658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  AutoLock lock(lock_);
18081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!CheckGeneration(generation) || !flush_message_loop_proxy_.get() ||
18091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      thread_message_loops_.size())
18101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
18114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
18124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  flush_message_loop_proxy_->PostTask(
18134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      FROM_HERE,
18144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      Bind(&TraceLog::FinishFlush, Unretained(this), generation));
181558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
181658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceLog::OnFlushTimeout(int generation) {
181858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  {
181958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    AutoLock lock(lock_);
18201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!CheckGeneration(generation) || !flush_message_loop_proxy_.get()) {
182158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // Flush has finished before timeout.
182258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return;
182358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
182458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
18258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    LOG(WARNING) <<
18268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        "The following threads haven't finished flush in time. "
18278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        "If this happens stably for some thread, please call "
18288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        "TraceLog::GetInstance()->SetCurrentThreadBlocksMessageLoop() from "
18298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        "the thread to avoid its trace events from being lost.";
18308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    for (hash_set<MessageLoop*>::const_iterator it =
18318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         thread_message_loops_.begin();
18328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         it != thread_message_loops_.end(); ++it) {
18338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      LOG(WARNING) << "Thread: " << (*it)->thread_name();
18348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
183558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
18364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  FinishFlush(generation);
18374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
18384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
18394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceLog::FlushButLeaveBufferIntact(
18404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const TraceLog::OutputCallback& flush_output_callback) {
18414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_ptr<TraceBuffer> previous_logged_events;
18424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  {
18434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AutoLock lock(lock_);
18444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    AddMetadataEventsWhileLocked();
18454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (thread_shared_chunk_) {
18464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      // Return the chunk to the main buffer to flush the sampling data.
18474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      logged_events_->ReturnChunk(thread_shared_chunk_index_,
18484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                  thread_shared_chunk_.Pass());
18494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
18504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    previous_logged_events = logged_events_->CloneForIteration().Pass();
18514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }  // release lock
18524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
18534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ConvertTraceEventsToTraceFormat(previous_logged_events.Pass(),
18544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                  flush_output_callback);
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void TraceLog::UseNextTraceBuffer() {
18585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  logged_events_.reset(CreateTraceBuffer());
18595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  subtle::NoBarrier_AtomicIncrement(&generation_, 1);
18605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  thread_shared_chunk_.reset();
18615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  thread_shared_chunk_index_ = 0;
18625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
18635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TraceEventHandle TraceLog::AddTraceEvent(
1865c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    char phase,
1866c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned char* category_group_enabled,
1867c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char* name,
1868c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned long long id,
1869c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int num_args,
1870c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char** arg_names,
1871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned char* arg_types,
1872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned long long* arg_values,
18734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const scoped_refptr<ConvertableToTraceFormat>* convertable_values,
1874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    unsigned char flags) {
18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeTicks now = base::TimeTicks::NowFromSystemTraceTime();
18778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return AddTraceEventWithThreadIdAndTimestamp(phase, category_group_enabled,
18788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                               name, id, thread_id, now,
18798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                               num_args, arg_names,
18808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                               arg_types, arg_values,
18818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                               convertable_values, flags);
18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TraceEventHandle TraceLog::AddTraceEventWithThreadIdAndTimestamp(
18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    char phase,
1886c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const unsigned char* category_group_enabled,
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* name,
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned long long id,
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int thread_id,
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const TimeTicks& timestamp,
18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int num_args,
18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char** arg_names,
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const unsigned char* arg_types,
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const unsigned long long* arg_values,
18954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const scoped_refptr<ConvertableToTraceFormat>* convertable_values,
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unsigned char flags) {
18971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  TraceEventHandle handle = { 0, 0, 0 };
18984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!*category_group_enabled)
18998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return handle;
19004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1901a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when
1902a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) ->
1903a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ...
1904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (thread_is_in_trace_event_.Get())
1905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return handle;
1906a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
1908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(name);
19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (flags & TRACE_EVENT_FLAG_MANGLE_ID)
19122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    id ^= process_id_hash_;
19132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19140f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  TimeTicks now = OffsetTimestamp(timestamp);
191558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  TimeTicks thread_now = ThreadNow();
19162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
191758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ThreadLocalEventBuffer* thread_local_event_buffer = NULL;
191858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // A ThreadLocalEventBuffer needs the message loop
191958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // - to know when the thread exits;
192058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // - to handle the final flush.
19218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // For a thread without a message loop or the message loop may be blocked, the
19228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // trace events will be added into the main buffer directly.
19238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (!thread_blocks_message_loop_.Get() && MessageLoop::current()) {
192458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    thread_local_event_buffer = thread_local_event_buffer_.Get();
19254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (thread_local_event_buffer &&
19264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        !CheckGeneration(thread_local_event_buffer->generation())) {
19274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      delete thread_local_event_buffer;
19284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      thread_local_event_buffer = NULL;
19294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    }
193058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (!thread_local_event_buffer) {
193158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      thread_local_event_buffer = new ThreadLocalEventBuffer(this);
193258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      thread_local_event_buffer_.Set(thread_local_event_buffer);
193358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
193458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
193558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1936ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Check and update the current thread name only if the event is for the
1937ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // current thread to avoid locks in most cases.
1938ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (thread_id == static_cast<int>(PlatformThread::CurrentId())) {
19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const char* new_name = ThreadIdNameManager::GetInstance()->
19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetName(thread_id);
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check if the thread name has been set or changed since the previous
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // call (if any), but don't bother if the new name is empty. Note this will
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // not detect a thread name change within the same char* buffer address: we
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // favor common case performance over corner case correctness.
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_name != g_current_thread_name.Get().Get() &&
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_name && *new_name) {
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_current_thread_name.Get().Set(new_name);
19482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      AutoLock thread_info_lock(thread_info_lock_);
1950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      hash_map<int, std::string>::iterator existing_name =
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          thread_names_.find(thread_id);
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_name == thread_names_.end()) {
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This is a new thread id, and a new name.
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        thread_names_[thread_id] = new_name;
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // This is a thread id that we've seen before, but potentially with a
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // new name.
19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        std::vector<StringPiece> existing_names;
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Tokenize(existing_name->second, ",", &existing_names);
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bool found = std::find(existing_names.begin(),
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               existing_names.end(),
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               new_name) != existing_names.end();
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!found) {
1965a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          if (existing_names.size())
1966a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            existing_name->second.push_back(',');
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          existing_name->second.append(new_name);
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1971ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1973a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string console_message;
19745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (*category_group_enabled &
19755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (ENABLED_FOR_RECORDING | ENABLED_FOR_MONITORING)) {
1976a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    OptionalAutoLock lock(lock_);
1977a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1978a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TraceEvent* trace_event = NULL;
197958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (thread_local_event_buffer) {
1980a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      trace_event = thread_local_event_buffer->AddTraceEvent(&handle);
198158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
19824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      lock.EnsureAcquired();
1983a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      trace_event = AddEventToThreadSharedChunkWhileLocked(&handle, true);
198458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
19857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
19864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (trace_event) {
19874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      trace_event->Initialize(thread_id, now, thread_now, phase,
19884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                              category_group_enabled, name, id,
19894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                              num_args, arg_names, arg_types, arg_values,
19904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                              convertable_values, flags);
19918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
19928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_ANDROID)
19938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      trace_event->SendToATrace();
19948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
1995c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1996c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
19975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (trace_options() & kInternalEchoToConsole) {
1998a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      console_message = EventToConsoleMessage(
1999a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          phase == TRACE_EVENT_PHASE_COMPLETE ? TRACE_EVENT_PHASE_BEGIN : phase,
2000a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          timestamp, trace_event);
2001a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
20021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
20031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2004a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (console_message.size())
2005a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << console_message;
2006a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
200758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (reinterpret_cast<const unsigned char*>(subtle::NoBarrier_Load(
200858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      &watch_category_)) == category_group_enabled) {
2009a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool event_name_matches;
2010a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    WatchEventCallback watch_event_callback_copy;
2011a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    {
2012a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      AutoLock lock(lock_);
2013a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      event_name_matches = watch_event_name_ == name;
2014a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      watch_event_callback_copy = watch_event_callback_;
2015a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
2016a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (event_name_matches) {
2017a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (!watch_event_callback_copy.is_null())
2018a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        watch_event_callback_copy.Run();
2019a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
202058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
20212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2022f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (*category_group_enabled & ENABLED_FOR_EVENT_CALLBACK) {
2023f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EventCallback event_callback = reinterpret_cast<EventCallback>(
2024f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        subtle::NoBarrier_Load(&event_callback_));
2025f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (event_callback) {
2026f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event_callback(now,
2027f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     phase == TRACE_EVENT_PHASE_COMPLETE ?
2028f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         TRACE_EVENT_PHASE_BEGIN : phase,
2029f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     category_group_enabled, name, id,
2030f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     num_args, arg_names, arg_types, arg_values,
2031f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     flags);
2032f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
20332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
203458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
203558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (thread_local_event_buffer)
2036a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    thread_local_event_buffer->ReportOverhead(now, thread_now);
20378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
20388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return handle;
20394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
20404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// May be called when a COMPELETE event ends and the unfinished event has been
20421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// recycled (phase == TRACE_EVENT_PHASE_END and trace_event == NULL).
2043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)std::string TraceLog::EventToConsoleMessage(unsigned char phase,
2044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            const TimeTicks& timestamp,
2045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            TraceEvent* trace_event) {
2046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AutoLock thread_info_lock(thread_info_lock_);
2047a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
20481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The caller should translate TRACE_EVENT_PHASE_COMPLETE to
20491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // TRACE_EVENT_PHASE_BEGIN or TRACE_EVENT_END.
20501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK(phase != TRACE_EVENT_PHASE_COMPLETE);
20514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  TimeDelta duration;
20531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int thread_id = trace_event ?
20541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      trace_event->thread_id() : PlatformThread::CurrentId();
20554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (phase == TRACE_EVENT_PHASE_END) {
20561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    duration = timestamp - thread_event_start_times_[thread_id].top();
20578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    thread_event_start_times_[thread_id].pop();
20584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
20594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::string thread_name = thread_names_[thread_id];
20614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (thread_colors_.find(thread_name) == thread_colors_.end())
20624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    thread_colors_[thread_name] = (thread_colors_.size() % 6) + 1;
20634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  std::ostringstream log;
20654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  log << base::StringPrintf("%s: \x1b[0;3%dm",
20664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            thread_name.c_str(),
20674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            thread_colors_[thread_name]);
20684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  size_t depth = 0;
20704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (thread_event_start_times_.find(thread_id) !=
20714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      thread_event_start_times_.end())
20724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    depth = thread_event_start_times_[thread_id].size();
20734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (size_t i = 0; i < depth; ++i)
20754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    log << "| ";
20764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (trace_event)
20781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    trace_event->AppendPrettyPrinted(&log);
20794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (phase == TRACE_EVENT_PHASE_END)
20804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    log << base::StringPrintf(" (%.3f ms)", duration.InMillisecondsF());
20814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2082a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  log << "\x1b[0;m";
20834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
20841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (phase == TRACE_EVENT_PHASE_BEGIN)
20851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    thread_event_start_times_[thread_id].push(timestamp);
2086a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2087a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return log.str();
20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::AddTraceEventEtw(char phase,
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char* name,
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const void* id,
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char* extra) {
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TraceEventETWProvider::Trace(name, phase, id, extra);
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::AddTraceEventEtw(char phase,
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const char* name,
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const void* id,
2104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                const std::string& extra) {
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TraceEventETWProvider::Trace(name, phase, id, extra);
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INTERNAL_TRACE_EVENT_ADD(phase, "ETW Trace Event", name,
21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           TRACE_EVENT_FLAG_COPY, "id", id, "extra", extra);
21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TraceLog::UpdateTraceEventDuration(
2113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const unsigned char* category_group_enabled,
2114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const char* name,
2115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TraceEventHandle handle) {
2116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Avoid re-entrance of AddTraceEvent. This may happen in GPU process when
2117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // ECHO_TO_CONSOLE is enabled: AddTraceEvent -> LOG(ERROR) ->
2118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // GpuProcessLogMessageHandler -> PostPendingTask -> TRACE_EVENT ...
2119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (thread_is_in_trace_event_.Get())
2120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
2121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AutoThreadLocalBoolean thread_is_in_trace_event(&thread_is_in_trace_event_);
2123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2124f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  TimeTicks thread_now = ThreadNow();
21250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  TimeTicks now = OffsetNow();
2126f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string console_message;
2128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (*category_group_enabled & ENABLED_FOR_RECORDING) {
2129f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    OptionalAutoLock lock(lock_);
2130f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
2131f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TraceEvent* trace_event = GetEventByHandleInternal(handle, &lock);
2132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (trace_event) {
2133f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      DCHECK(trace_event->phase() == TRACE_EVENT_PHASE_COMPLETE);
2134f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      trace_event->UpdateDuration(now, thread_now);
21358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#if defined(OS_ANDROID)
2136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      trace_event->SendToATrace();
21378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#endif
2138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
21398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
21405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    if (trace_options() & kInternalEchoToConsole) {
2141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      console_message = EventToConsoleMessage(TRACE_EVENT_PHASE_END,
2142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                              now, trace_event);
2143f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
21441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
21451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
2146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (console_message.size())
2147a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << console_message;
2148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
2149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (*category_group_enabled & ENABLED_FOR_EVENT_CALLBACK) {
2150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    EventCallback event_callback = reinterpret_cast<EventCallback>(
2151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        subtle::NoBarrier_Load(&event_callback_));
2152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (event_callback) {
2153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      event_callback(now, TRACE_EVENT_PHASE_END, category_group_enabled, name,
2154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     trace_event_internal::kNoEventId, 0, NULL, NULL, NULL,
2155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     TRACE_EVENT_FLAG_NONE);
2156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
21578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
21588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
21598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::SetWatchEvent(const std::string& category_name,
2161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             const std::string& event_name,
2162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                             const WatchEventCallback& callback) {
2163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const unsigned char* category = GetCategoryGroupEnabled(
2164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      category_name.c_str());
21654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  AutoLock lock(lock_);
21664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  subtle::NoBarrier_Store(&watch_category_,
21674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                          reinterpret_cast<subtle::AtomicWord>(category));
21684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  watch_event_name_ = event_name;
2169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  watch_event_callback_ = callback;
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::CancelWatchEvent() {
21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AutoLock lock(lock_);
217458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  subtle::NoBarrier_Store(&watch_category_, 0);
21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  watch_event_name_ = "";
2176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  watch_event_callback_.Reset();
21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void TraceLog::AddMetadataEventsWhileLocked() {
21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  lock_.AssertAcquired();
21817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
2182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#if !defined(OS_NACL)  // NaCl shouldn't expose the process id.
2183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
2184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          0,
2185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          "num_cpus", "number",
2186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          base::SysInfo::NumberOfProcessors());
2187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#endif
2188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
2189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
21907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  int current_thread_id = static_cast<int>(base::PlatformThread::CurrentId());
21917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (process_sort_index_ != 0) {
2192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
21934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            current_thread_id,
21944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            "process_sort_index", "sort_index",
21954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            process_sort_index_);
21967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
21977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
21987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (process_name_.size()) {
2199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
22004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            current_thread_id,
22014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            "process_name", "name",
22024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            process_name_);
22037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
22047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
22057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (process_labels_.size() > 0) {
22067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    std::vector<std::string> labels;
22077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for(base::hash_map<int, std::string>::iterator it = process_labels_.begin();
22087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        it != process_labels_.end();
22097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        it++) {
22107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      labels.push_back(it->second);
22117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
22134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            current_thread_id,
22144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            "process_labels", "labels",
22154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            JoinString(labels, ','));
22167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
22177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
22187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Thread sort indices.
22197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for(hash_map<int, int>::iterator it = thread_sort_indices_.begin();
22207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      it != thread_sort_indices_.end();
22217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      it++) {
22227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (it->second == 0)
22237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      continue;
2224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
22254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            it->first,
22264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            "thread_sort_index", "sort_index",
22274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            it->second);
22287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
22297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
22307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // Thread names.
2231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  AutoLock thread_info_lock(thread_info_lock_);
22322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for(hash_map<int, std::string>::iterator it = thread_names_.begin();
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it != thread_names_.end();
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it++) {
22357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (it->second.empty())
22367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      continue;
2237a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
22384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            it->first,
22394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            "thread_name", "name",
22404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            it->second);
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
22435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // If buffer is full, add a metadata record to report this.
22445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!buffer_limit_reached_timestamp_.is_null()) {
22455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    InitializeMetadataEvent(AddEventToThreadSharedChunkWhileLocked(NULL, false),
22465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            current_thread_id,
22475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "trace_buffer_overflowed",
22485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            "overflowed_at_ts",
22495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                            buffer_limit_reached_timestamp_);
22505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void TraceLog::WaitSamplingEventForTesting() {
22544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!sampling_thread_)
22554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
2256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  sampling_thread_->WaitSamplingEventForTesting();
22572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
22582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::DeleteForTesting() {
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteTraceLogForTesting::Delete();
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TraceEvent* TraceLog::GetEventByHandle(TraceEventHandle handle) {
22648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return GetEventByHandleInternal(handle, NULL);
22658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
22664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
22678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)TraceEvent* TraceLog::GetEventByHandleInternal(TraceEventHandle handle,
22688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                               OptionalAutoLock* lock) {
22691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (!handle.chunk_seq)
22701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return NULL;
22711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
22724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (thread_local_event_buffer_.Get()) {
22738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    TraceEvent* trace_event =
22748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        thread_local_event_buffer_.Get()->GetEventByHandle(handle);
22754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (trace_event)
22764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      return trace_event;
22774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
22784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
22798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // The event has been out-of-control of the thread local buffer.
22808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Try to get the event from the main buffer with a lock.
22818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (lock)
22828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    lock->EnsureAcquired();
22834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
22848bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (thread_shared_chunk_ &&
22858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      handle.chunk_index == thread_shared_chunk_index_) {
22868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return handle.chunk_seq == thread_shared_chunk_->seq() ?
22878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        thread_shared_chunk_->GetEventAt(handle.event_index) : NULL;
22888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
22898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
22908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return logged_events_->GetEventByHandle(handle);
22914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
22924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TraceLog::SetProcessID(int process_id) {
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_id_ = process_id;
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a FNV hash from the process ID for XORing.
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See http://isthe.com/chongo/tech/comp/fnv/ for algorithm details.
22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long offset_basis = 14695981039346656037ull;
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long fnv_prime = 1099511628211ull;
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long long pid = static_cast<unsigned long long>(process_id_);
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_id_hash_ = (offset_basis ^ pid) * fnv_prime;
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid TraceLog::SetProcessSortIndex(int sort_index) {
23047dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AutoLock lock(lock_);
23057dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  process_sort_index_ = sort_index;
23067dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
23077dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
23087dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid TraceLog::SetProcessName(const std::string& process_name) {
23097dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AutoLock lock(lock_);
23107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  process_name_ = process_name;
23117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
23127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
23137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid TraceLog::UpdateProcessLabel(
23147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int label_id, const std::string& current_label) {
23157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if(!current_label.length())
23167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return RemoveProcessLabel(label_id);
23177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
23187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AutoLock lock(lock_);
23197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  process_labels_[label_id] = current_label;
23207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
23217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
23227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid TraceLog::RemoveProcessLabel(int label_id) {
2323ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  AutoLock lock(lock_);
23247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::hash_map<int, std::string>::iterator it = process_labels_.find(
23254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      label_id);
23267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if (it == process_labels_.end())
23277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
23287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
23297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  process_labels_.erase(it);
23307dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
23317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
23327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid TraceLog::SetThreadSortIndex(PlatformThreadId thread_id, int sort_index) {
23337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  AutoLock lock(lock_);
23347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  thread_sort_indices_[static_cast<int>(thread_id)] = sort_index;
23357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
23367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
23372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TraceLog::SetTimeOffset(TimeDelta offset) {
23382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  time_offset_ = offset;
23392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
23402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
23417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)size_t TraceLog::GetObserverCountForTest() const {
23427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return enabled_state_observer_list_.size();
23437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
23447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
23458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void TraceLog::SetCurrentThreadBlocksMessageLoop() {
23468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  thread_blocks_message_loop_.Set(true);
23478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (thread_local_event_buffer_.Get()) {
23488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // This will flush the thread local buffer.
23498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    delete thread_local_event_buffer_.Get();
23508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
23518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
23528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
2353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace(
2354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const std::string& str) {
2355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return  str.empty() ||
2356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          str.at(0) == ' ' ||
2357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          str.at(str.length() - 1) == ' ';
2358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2360b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool CategoryFilter::DoesCategoryGroupContainCategory(
2361b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const char* category_group,
2362b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const char* category) const {
2363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(category);
2364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CStringTokenizer category_group_tokens(category_group,
2365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          category_group + strlen(category_group), ",");
2366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (category_group_tokens.GetNext()) {
2367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string category_group_token = category_group_tokens.token();
2368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Don't allow empty tokens, nor tokens with leading or trailing space.
2369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(!CategoryFilter::IsEmptyOrContainsLeadingOrTrailingWhitespace(
2370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        category_group_token))
2371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        << "Disallowed category string";
2372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (MatchPattern(category_group_token.c_str(), category))
2373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return true;
2374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return false;
2376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CategoryFilter::CategoryFilter(const std::string& filter_string) {
2379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!filter_string.empty())
2380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Initialize(filter_string);
2381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else
2382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Initialize(CategoryFilter::kDefaultCategoryFilterString);
2383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
23855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)CategoryFilter::CategoryFilter() {
23865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    Initialize(CategoryFilter::kDefaultCategoryFilterString);
23875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
23885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2389c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CategoryFilter::CategoryFilter(const CategoryFilter& cf)
2390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : included_(cf.included_),
2391b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      disabled_(cf.disabled_),
23925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      excluded_(cf.excluded_),
23935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      delays_(cf.delays_) {
2394c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CategoryFilter::~CategoryFilter() {
2397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)CategoryFilter& CategoryFilter::operator=(const CategoryFilter& rhs) {
2400c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (this == &rhs)
2401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return *this;
2402c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2403c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  included_ = rhs.included_;
2404b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  disabled_ = rhs.disabled_;
2405c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  excluded_ = rhs.excluded_;
24065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delays_ = rhs.delays_;
2407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return *this;
2408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CategoryFilter::Initialize(const std::string& filter_string) {
2411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Tokenize list of categories, delimited by ','.
2412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  StringTokenizer tokens(filter_string, ",");
2413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Add each token to the appropriate list (included_,excluded_).
2414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (tokens.GetNext()) {
2415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string category = tokens.token();
2416c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Ignore empty categories.
2417c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (category.empty())
2418c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
24195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Synthetic delays are of the form 'DELAY(delay;option;option;...)'.
24205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (category.find(kSyntheticDelayCategoryFilterPrefix) == 0 &&
24215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        category.at(category.size() - 1) == ')') {
24225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      category = category.substr(
24235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          strlen(kSyntheticDelayCategoryFilterPrefix),
24245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          category.size() - strlen(kSyntheticDelayCategoryFilterPrefix) - 1);
24255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      size_t name_length = category.find(';');
24265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (name_length != std::string::npos && name_length > 0 &&
24275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          name_length != category.size() - 1) {
24285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        delays_.push_back(category);
24295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
24305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (category.at(0) == '-') {
24315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Excluded categories start with '-'.
2432c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Remove '-' from category string.
2433c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      category = category.substr(1);
2434c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      excluded_.push_back(category);
2435b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    } else if (category.compare(0, strlen(TRACE_DISABLED_BY_DEFAULT("")),
2436b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                TRACE_DISABLED_BY_DEFAULT("")) == 0) {
2437b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      disabled_.push_back(category);
2438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    } else {
2439c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      included_.push_back(category);
2440c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
2441c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2442c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2443c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2444b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)void CategoryFilter::WriteString(const StringList& values,
2445b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                 std::string* out,
2446c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 bool included) const {
2447b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  bool prepend_comma = !out->empty();
2448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int token_cnt = 0;
2449b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (StringList::const_iterator ci = values.begin();
2450b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       ci != values.end(); ++ci) {
2451b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (token_cnt > 0 || prepend_comma)
2452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      StringAppendF(out, ",");
2453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    StringAppendF(out, "%s%s", (included ? "" : "-"), ci->c_str());
2454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ++token_cnt;
2455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
24585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CategoryFilter::WriteString(const StringList& delays,
24595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                 std::string* out) const {
24605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool prepend_comma = !out->empty();
24615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  int token_cnt = 0;
24625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (StringList::const_iterator ci = delays.begin();
24635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ci != delays.end(); ++ci) {
24645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (token_cnt > 0 || prepend_comma)
24655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      StringAppendF(out, ",");
24665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StringAppendF(out, "%s%s)", kSyntheticDelayCategoryFilterPrefix,
24675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  ci->c_str());
24685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ++token_cnt;
24695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
24705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
24715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2472c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string CategoryFilter::ToString() const {
2473c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  std::string filter_string;
2474b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  WriteString(included_, &filter_string, true);
2475b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  WriteString(disabled_, &filter_string, true);
2476b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  WriteString(excluded_, &filter_string, false);
24775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  WriteString(delays_, &filter_string);
2478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return filter_string;
2479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2481c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CategoryFilter::IsCategoryGroupEnabled(
2482c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const char* category_group_name) const {
2483c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // TraceLog should call this method only as  part of enabling/disabling
2484c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // categories.
2485b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  StringList::const_iterator ci;
2486b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2487b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Check the disabled- filters and the disabled-* wildcard first so that a
2488b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // "*" filter does not include the disabled.
2489b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (ci = disabled_.begin(); ci != disabled_.end(); ++ci) {
2490b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
2491b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return true;
2492b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
2493b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (DoesCategoryGroupContainCategory(category_group_name,
2494b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                       TRACE_DISABLED_BY_DEFAULT("*")))
2495b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
2496b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2497b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (ci = included_.begin(); ci != included_.end(); ++ci) {
2498c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
2499c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return true;
2500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2501b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2502b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  for (ci = excluded_.begin(); ci != excluded_.end(); ++ci) {
2503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (DoesCategoryGroupContainCategory(category_group_name, ci->c_str()))
2504c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return false;
2505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
2506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the category group is not excluded, and there are no included patterns
2507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // we consider this pattern enabled.
2508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return included_.empty();
2509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2511b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool CategoryFilter::HasIncludedPatterns() const {
2512b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return !included_.empty();
2513b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
2514b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CategoryFilter::Merge(const CategoryFilter& nested_filter) {
2516b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Keep included patterns only if both filters have an included entry.
2517b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Otherwise, one of the filter was specifying "*" and we want to honour the
2518b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // broadest filter.
2519b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (HasIncludedPatterns() && nested_filter.HasIncludedPatterns()) {
2520b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    included_.insert(included_.end(),
2521b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     nested_filter.included_.begin(),
2522b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                     nested_filter.included_.end());
2523b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  } else {
2524b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    included_.clear();
2525b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
2526b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
2527b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  disabled_.insert(disabled_.end(),
2528b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   nested_filter.disabled_.begin(),
2529b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                   nested_filter.disabled_.end());
2530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  excluded_.insert(excluded_.end(),
2531c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   nested_filter.excluded_.begin(),
2532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   nested_filter.excluded_.end());
25335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  delays_.insert(delays_.end(),
25345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 nested_filter.delays_.begin(),
25355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 nested_filter.delays_.end());
2536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2538c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CategoryFilter::Clear() {
2539c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  included_.clear();
2540b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  disabled_.clear();
2541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  excluded_.clear();
2542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
2543c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
25445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const CategoryFilter::StringList&
25455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CategoryFilter::GetSyntheticDelayValues() const {
25465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return delays_;
25475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
25485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace debug
25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
25512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace trace_event_internal {
25532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ScopedTraceBinaryEfficient::ScopedTraceBinaryEfficient(
25558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const char* category_group, const char* name) {
25568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // The single atom works because for now the category_group can only be "gpu".
25578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(strcmp(category_group, "gpu") == 0);
25588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  static TRACE_EVENT_API_ATOMIC_WORD atomic = 0;
25598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO_CUSTOM_VARIABLES(
25608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      category_group, atomic, category_group_enabled_);
2561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  name_ = name;
2562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (*category_group_enabled_) {
25638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    event_handle_ =
25648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
25658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            TRACE_EVENT_PHASE_COMPLETE, category_group_enabled_, name,
25668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            trace_event_internal::kNoEventId,
25678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            static_cast<int>(base::PlatformThread::CurrentId()),
25688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            base::TimeTicks::NowFromSystemTraceTime(),
25698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)            0, NULL, NULL, NULL, NULL, TRACE_EVENT_FLAG_NONE);
25702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
25712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
25722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() {
2574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (*category_group_enabled_) {
2575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_,
2576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                                name_, event_handle_);
2577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
25782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
25792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
25802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace trace_event_internal
2581