OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/debug/trace_event_impl.h" | 5 #include "base/debug/trace_event_impl.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/base_switches.h" | 9 #include "base/base_switches.h" |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 "trace_event_overhead"}; | 93 "trace_event_overhead"}; |
94 | 94 |
95 // The enabled flag is char instead of bool so that the API can be used from C. | 95 // The enabled flag is char instead of bool so that the API can be used from C. |
96 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 }; | 96 unsigned char g_category_group_enabled[MAX_CATEGORY_GROUPS] = { 0 }; |
97 // Indexes here have to match the g_category_groups array indexes above. | 97 // Indexes here have to match the g_category_groups array indexes above. |
98 const int g_category_already_shutdown = 1; | 98 const int g_category_already_shutdown = 1; |
99 const int g_category_categories_exhausted = 2; | 99 const int g_category_categories_exhausted = 2; |
100 const int g_category_metadata = 3; | 100 const int g_category_metadata = 3; |
101 const int g_category_trace_event_overhead = 4; | 101 const int g_category_trace_event_overhead = 4; |
102 const int g_num_builtin_categories = 5; | 102 const int g_num_builtin_categories = 5; |
103 int g_category_index = g_num_builtin_categories; // Skip default categories. | 103 // Skip default categories. |
104 base::subtle::AtomicWord g_category_index = g_num_builtin_categories; | |
104 | 105 |
105 // The name of the current thread. This is used to decide if the current | 106 // The name of the current thread. This is used to decide if the current |
106 // thread name has changed. We combine all the seen thread names into the | 107 // thread name has changed. We combine all the seen thread names into the |
107 // output name for the thread. | 108 // output name for the thread. |
108 LazyInstance<ThreadLocalPointer<const char> >::Leaky | 109 LazyInstance<ThreadLocalPointer<const char> >::Leaky |
109 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; | 110 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
110 | 111 |
111 TimeTicks ThreadNow() { | 112 TimeTicks ThreadNow() { |
112 return TimeTicks::IsThreadNowSupported() ? | 113 return TimeTicks::IsThreadNowSupported() ? |
113 TimeTicks::ThreadNow() : TimeTicks(); | 114 TimeTicks::ThreadNow() : TimeTicks(); |
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1252 delay->SetMode(TraceEventSyntheticDelay::ALTERNATING); | 1253 delay->SetMode(TraceEventSyntheticDelay::ALTERNATING); |
1253 } | 1254 } |
1254 } | 1255 } |
1255 } | 1256 } |
1256 } | 1257 } |
1257 | 1258 |
1258 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( | 1259 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( |
1259 const char* category_group) { | 1260 const char* category_group) { |
1260 DCHECK(!strchr(category_group, '"')) << | 1261 DCHECK(!strchr(category_group, '"')) << |
1261 "Category groups may not contain double quote"; | 1262 "Category groups may not contain double quote"; |
1262 AutoLock lock(lock_); | 1263 // The g_category_groups is append only, avoid using a lock for the fast path. |
1264 int current_category_index = base::subtle::NoBarrier_Load(&g_category_index); | |
1263 | 1265 |
1264 unsigned char* category_group_enabled = NULL; | |
1265 // Search for pre-existing category group. | 1266 // Search for pre-existing category group. |
1266 for (int i = 0; i < g_category_index; i++) { | 1267 for (int i = 0; i < current_category_index; ++i) { |
1267 if (strcmp(g_category_groups[i], category_group) == 0) { | 1268 if (strcmp(g_category_groups[i], category_group) == 0) { |
1268 category_group_enabled = &g_category_group_enabled[i]; | 1269 return &g_category_group_enabled[i]; |
1269 break; | |
1270 } | 1270 } |
1271 } | 1271 } |
1272 | 1272 |
1273 if (!category_group_enabled) { | 1273 unsigned char* category_group_enabled = NULL; |
1274 // Create a new category group | 1274 // This is the slow path: the lock is not held in the case above, so more |
1275 DCHECK(g_category_index < MAX_CATEGORY_GROUPS) << | 1275 // than one thread could have reached here trying to add the same category. |
1276 "must increase MAX_CATEGORY_GROUPS"; | 1276 // Only hold to lock when actually appending a new category, and |
1277 if (g_category_index < MAX_CATEGORY_GROUPS) { | 1277 // check the categories groups again. |
1278 int new_index = g_category_index++; | 1278 AutoLock lock(lock_); |
1279 // Don't hold on to the category_group pointer, so that we can create | 1279 for (int i = 0; i < g_category_index; ++i) { |
1280 // category groups with strings not known at compile time (this is | 1280 if (strcmp(g_category_groups[i], category_group) == 0) { |
1281 // required by SetWatchEvent). | 1281 return &g_category_group_enabled[i]; |
1282 const char* new_group = strdup(category_group); | |
1283 ANNOTATE_LEAKING_OBJECT_PTR(new_group); | |
1284 g_category_groups[new_index] = new_group; | |
1285 DCHECK(!g_category_group_enabled[new_index]); | |
1286 // Note that if both included and excluded patterns in the | |
1287 // CategoryFilter are empty, we exclude nothing, | |
1288 // thereby enabling this category group. | |
1289 UpdateCategoryGroupEnabledFlag(new_index); | |
1290 category_group_enabled = &g_category_group_enabled[new_index]; | |
1291 } else { | |
1292 category_group_enabled = | |
1293 &g_category_group_enabled[g_category_categories_exhausted]; | |
1294 } | 1282 } |
1295 } | 1283 } |
1284 | |
1285 // Create a new category group. | |
1286 DCHECK(g_category_index < MAX_CATEGORY_GROUPS) << | |
1287 "must increase MAX_CATEGORY_GROUPS"; | |
1288 if (g_category_index < MAX_CATEGORY_GROUPS) { | |
1289 int new_index = base::subtle::Acquire_Load(&g_category_index); | |
bulach
2014/02/13 17:55:37
the + 1 was here.. :(
| |
1290 // Don't hold on to the category_group pointer, so that we can create | |
1291 // category groups with strings not known at compile time (this is | |
1292 // required by SetWatchEvent). | |
1293 const char* new_group = strdup(category_group); | |
1294 ANNOTATE_LEAKING_OBJECT_PTR(new_group); | |
1295 g_category_groups[new_index] = new_group; | |
1296 DCHECK(!g_category_group_enabled[new_index]); | |
1297 // Note that if both included and excluded patterns in the | |
1298 // CategoryFilter are empty, we exclude nothing, | |
1299 // thereby enabling this category group. | |
1300 UpdateCategoryGroupEnabledFlag(new_index); | |
1301 category_group_enabled = &g_category_group_enabled[new_index]; | |
1302 // Update the max index now. | |
1303 base::subtle::Release_Store(&g_category_index, new_index + 1); | |
1304 } else { | |
1305 category_group_enabled = | |
1306 &g_category_group_enabled[g_category_categories_exhausted]; | |
1307 } | |
1296 return category_group_enabled; | 1308 return category_group_enabled; |
1297 } | 1309 } |
1298 | 1310 |
1299 void TraceLog::GetKnownCategoryGroups( | 1311 void TraceLog::GetKnownCategoryGroups( |
1300 std::vector<std::string>* category_groups) { | 1312 std::vector<std::string>* category_groups) { |
1301 AutoLock lock(lock_); | 1313 AutoLock lock(lock_); |
1302 category_groups->push_back( | 1314 category_groups->push_back( |
1303 g_category_groups[g_category_trace_event_overhead]); | 1315 g_category_groups[g_category_trace_event_overhead]); |
1304 for (int i = g_num_builtin_categories; i < g_category_index; i++) | 1316 for (int i = g_num_builtin_categories; i < g_category_index; i++) |
1305 category_groups->push_back(g_category_groups[i]); | 1317 category_groups->push_back(g_category_groups[i]); |
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2405 } | 2417 } |
2406 | 2418 |
2407 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 2419 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
2408 if (*category_group_enabled_) { | 2420 if (*category_group_enabled_) { |
2409 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, | 2421 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
2410 name_, event_handle_); | 2422 name_, event_handle_); |
2411 } | 2423 } |
2412 } | 2424 } |
2413 | 2425 |
2414 } // namespace trace_event_internal | 2426 } // namespace trace_event_internal |
OLD | NEW |