Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / base / debug / trace_event_impl.cc
index ce25c38..a01a103 100644 (file)
@@ -71,8 +71,10 @@ const size_t kEchoToConsoleTraceEventBufferChunks = 256;
 
 const int kThreadFlushTimeoutMs = 3000;
 
+#if !defined(OS_NACL)
 // These categories will cause deadlock when ECHO_TO_CONSOLE. crbug.com/325575.
 const char kEchoToConsoleCategoryFilter[] = "-ipc,-task";
+#endif
 
 const char kSyntheticDelayCategoryFilterPrefix[] = "DELAY(";
 
@@ -100,7 +102,8 @@ const int g_category_categories_exhausted = 2;
 const int g_category_metadata = 3;
 const int g_category_trace_event_overhead = 4;
 const int g_num_builtin_categories = 5;
-int g_category_index = g_num_builtin_categories; // Skip default categories.
+// Skip default categories.
+base::subtle::AtomicWord g_category_index = g_num_builtin_categories;
 
 // The name of the current thread. This is used to decide if the current
 // thread name has changed. We combine all the seen thread names into the
@@ -1222,7 +1225,8 @@ void TraceLog::UpdateCategoryGroupEnabledFlag(int category_index) {
 }
 
 void TraceLog::UpdateCategoryGroupEnabledFlags() {
-  for (int i = 0; i < g_category_index; i++)
+  int category_index = base::subtle::NoBarrier_Load(&g_category_index);
+  for (int i = 0; i < category_index; i++)
     UpdateCategoryGroupEnabledFlag(i);
 }
 
@@ -1259,40 +1263,51 @@ const unsigned char* TraceLog::GetCategoryGroupEnabledInternal(
     const char* category_group) {
   DCHECK(!strchr(category_group, '"')) <<
       "Category groups may not contain double quote";
-  AutoLock lock(lock_);
+  // The g_category_groups is append only, avoid using a lock for the fast path.
+  int current_category_index = base::subtle::Acquire_Load(&g_category_index);
 
-  unsigned char* category_group_enabled = NULL;
   // Search for pre-existing category group.
-  for (int i = 0; i < g_category_index; i++) {
+  for (int i = 0; i < current_category_index; ++i) {
     if (strcmp(g_category_groups[i], category_group) == 0) {
-      category_group_enabled = &g_category_group_enabled[i];
-      break;
+      return &g_category_group_enabled[i];
     }
   }
 
-  if (!category_group_enabled) {
-    // Create a new category group
-    DCHECK(g_category_index < MAX_CATEGORY_GROUPS) <<
-        "must increase MAX_CATEGORY_GROUPS";
-    if (g_category_index < MAX_CATEGORY_GROUPS) {
-      int new_index = g_category_index++;
-      // Don't hold on to the category_group pointer, so that we can create
-      // category groups with strings not known at compile time (this is
-      // required by SetWatchEvent).
-      const char* new_group = strdup(category_group);
-      ANNOTATE_LEAKING_OBJECT_PTR(new_group);
-      g_category_groups[new_index] = new_group;
-      DCHECK(!g_category_group_enabled[new_index]);
-      // Note that if both included and excluded patterns in the
-      // CategoryFilter are empty, we exclude nothing,
-      // thereby enabling this category group.
-      UpdateCategoryGroupEnabledFlag(new_index);
-      category_group_enabled = &g_category_group_enabled[new_index];
-    } else {
-      category_group_enabled =
-          &g_category_group_enabled[g_category_categories_exhausted];
+  unsigned char* category_group_enabled = NULL;
+  // This is the slow path: the lock is not held in the case above, so more
+  // than one thread could have reached here trying to add the same category.
+  // Only hold to lock when actually appending a new category, and
+  // check the categories groups again.
+  AutoLock lock(lock_);
+  int category_index = base::subtle::Acquire_Load(&g_category_index);
+  for (int i = 0; i < category_index; ++i) {
+    if (strcmp(g_category_groups[i], category_group) == 0) {
+      return &g_category_group_enabled[i];
     }
   }
+
+  // Create a new category group.
+  DCHECK(category_index < MAX_CATEGORY_GROUPS) <<
+      "must increase MAX_CATEGORY_GROUPS";
+  if (category_index < MAX_CATEGORY_GROUPS) {
+    // Don't hold on to the category_group pointer, so that we can create
+    // category groups with strings not known at compile time (this is
+    // required by SetWatchEvent).
+    const char* new_group = strdup(category_group);
+    ANNOTATE_LEAKING_OBJECT_PTR(new_group);
+    g_category_groups[category_index] = new_group;
+    DCHECK(!g_category_group_enabled[category_index]);
+    // Note that if both included and excluded patterns in the
+    // CategoryFilter are empty, we exclude nothing,
+    // thereby enabling this category group.
+    UpdateCategoryGroupEnabledFlag(category_index);
+    category_group_enabled = &g_category_group_enabled[category_index];
+    // Update the max index now.
+    base::subtle::Release_Store(&g_category_index, category_index + 1);
+  } else {
+    category_group_enabled =
+        &g_category_group_enabled[g_category_categories_exhausted];
+  }
   return category_group_enabled;
 }
 
@@ -1301,7 +1316,8 @@ void TraceLog::GetKnownCategoryGroups(
   AutoLock lock(lock_);
   category_groups->push_back(
       g_category_groups[g_category_trace_event_overhead]);
-  for (int i = g_num_builtin_categories; i < g_category_index; i++)
+  int category_index = base::subtle::NoBarrier_Load(&g_category_index);
+  for (int i = g_num_builtin_categories; i < category_index; i++)
     category_groups->push_back(g_category_groups[i]);
 }
 
@@ -1319,12 +1335,12 @@ void TraceLog::SetEnabled(const CategoryFilter& category_filter,
 
     if (IsEnabled()) {
       if (options != old_options) {
-        DLOG(ERROR) << "Attemting to re-enable tracing with a different "
+        DLOG(ERROR) << "Attempting to re-enable tracing with a different "
                     << "set of options.";
       }
 
       if (mode != mode_) {
-        DLOG(ERROR) << "Attemting to re-enable tracing with a different mode.";
+        DLOG(ERROR) << "Attempting to re-enable tracing with a different mode.";
       }
 
       category_filter_.Merge(category_filter);
@@ -1955,8 +1971,7 @@ void TraceLog::AddTraceEventEtw(char phase,
 void TraceLog::AddTraceEventEtw(char phase,
                                 const char* name,
                                 const void* id,
-                                const std::string& extra)
-{
+                                const std::string& extra) {
 #if defined(OS_WIN)
   TraceEventETWProvider::Trace(name, phase, id, extra);
 #endif