Chromium Code Reviews| Index: base/debug/trace_event_impl.cc |
| diff --git a/base/debug/trace_event_impl.cc b/base/debug/trace_event_impl.cc |
| index ce25c387f3ef0f00fe57b8fe14694dd8fb8ebbc1..566520818703b049d15f5497875c8e2d1b8e458c 100644 |
| --- a/base/debug/trace_event_impl.cc |
| +++ b/base/debug/trace_event_impl.cc |
| @@ -100,7 +100,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 |
| @@ -1259,40 +1260,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::NoBarrier_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_); |
| + for (int i = 0; i < g_category_index; ++i) { |
| + if (strcmp(g_category_groups[i], category_group) == 0) { |
| + return &g_category_group_enabled[i]; |
| } |
| } |
| + |
| + // 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 = base::subtle::Acquire_Load(&g_category_index); |
|
bulach
2014/02/13 17:55:37
the + 1 was here.. :(
|
| + // 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]; |
| + // Update the max index now. |
| + base::subtle::Release_Store(&g_category_index, new_index + 1); |
| + } else { |
| + category_group_enabled = |
| + &g_category_group_enabled[g_category_categories_exhausted]; |
| + } |
| return category_group_enabled; |
| } |