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 // Skip default categories. | 103 int g_category_index = g_num_builtin_categories; // Skip default categories. |
104 base::subtle::AtomicWord g_category_index = g_num_builtin_categories; | |
105 | 104 |
106 // The name of the current thread. This is used to decide if the current | 105 // The name of the current thread. This is used to decide if the current |
107 // thread name has changed. We combine all the seen thread names into the | 106 // thread name has changed. We combine all the seen thread names into the |
108 // output name for the thread. | 107 // output name for the thread. |
109 LazyInstance<ThreadLocalPointer<const char> >::Leaky | 108 LazyInstance<ThreadLocalPointer<const char> >::Leaky |
110 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; | 109 g_current_thread_name = LAZY_INSTANCE_INITIALIZER; |
111 | 110 |
112 TimeTicks ThreadNow() { | 111 TimeTicks ThreadNow() { |
113 return TimeTicks::IsThreadNowSupported() ? | 112 return TimeTicks::IsThreadNowSupported() ? |
114 TimeTicks::ThreadNow() : TimeTicks(); | 113 TimeTicks::ThreadNow() : TimeTicks(); |
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1253 delay->SetMode(TraceEventSyntheticDelay::ALTERNATING); | 1252 delay->SetMode(TraceEventSyntheticDelay::ALTERNATING); |
1254 } | 1253 } |
1255 } | 1254 } |
1256 } | 1255 } |
1257 } | 1256 } |
1258 | 1257 |
1259 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( | 1258 const unsigned char* TraceLog::GetCategoryGroupEnabledInternal( |
1260 const char* category_group) { | 1259 const char* category_group) { |
1261 DCHECK(!strchr(category_group, '"')) << | 1260 DCHECK(!strchr(category_group, '"')) << |
1262 "Category groups may not contain double quote"; | 1261 "Category groups may not contain double quote"; |
1263 // The g_category_groups is append only, avoid using a lock for the fast path. | 1262 AutoLock lock(lock_); |
1264 int current_category_index = base::subtle::NoBarrier_Load(&g_category_index); | |
1265 | 1263 |
| 1264 unsigned char* category_group_enabled = NULL; |
1266 // Search for pre-existing category group. | 1265 // Search for pre-existing category group. |
1267 for (int i = 0; i < current_category_index; ++i) { | 1266 for (int i = 0; i < g_category_index; i++) { |
1268 if (strcmp(g_category_groups[i], category_group) == 0) { | 1267 if (strcmp(g_category_groups[i], category_group) == 0) { |
1269 return &g_category_group_enabled[i]; | 1268 category_group_enabled = &g_category_group_enabled[i]; |
| 1269 break; |
1270 } | 1270 } |
1271 } | 1271 } |
1272 | 1272 |
1273 unsigned char* category_group_enabled = NULL; | 1273 if (!category_group_enabled) { |
1274 // This is the slow path: the lock is not held in the case above, so more | 1274 // Create a new category group |
1275 // than one thread could have reached here trying to add the same category. | 1275 DCHECK(g_category_index < MAX_CATEGORY_GROUPS) << |
1276 // Only hold to lock when actually appending a new category, and | 1276 "must increase MAX_CATEGORY_GROUPS"; |
1277 // check the categories groups again. | 1277 if (g_category_index < MAX_CATEGORY_GROUPS) { |
1278 AutoLock lock(lock_); | 1278 int new_index = g_category_index++; |
1279 for (int i = 0; i < g_category_index; ++i) { | 1279 // Don't hold on to the category_group pointer, so that we can create |
1280 if (strcmp(g_category_groups[i], category_group) == 0) { | 1280 // category groups with strings not known at compile time (this is |
1281 return &g_category_group_enabled[i]; | 1281 // required by SetWatchEvent). |
| 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]; |
1282 } | 1294 } |
1283 } | 1295 } |
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); | |
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 } | |
1308 return category_group_enabled; | 1296 return category_group_enabled; |
1309 } | 1297 } |
1310 | 1298 |
1311 void TraceLog::GetKnownCategoryGroups( | 1299 void TraceLog::GetKnownCategoryGroups( |
1312 std::vector<std::string>* category_groups) { | 1300 std::vector<std::string>* category_groups) { |
1313 AutoLock lock(lock_); | 1301 AutoLock lock(lock_); |
1314 category_groups->push_back( | 1302 category_groups->push_back( |
1315 g_category_groups[g_category_trace_event_overhead]); | 1303 g_category_groups[g_category_trace_event_overhead]); |
1316 for (int i = g_num_builtin_categories; i < g_category_index; i++) | 1304 for (int i = g_num_builtin_categories; i < g_category_index; i++) |
1317 category_groups->push_back(g_category_groups[i]); | 1305 category_groups->push_back(g_category_groups[i]); |
(...skipping 1099 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2417 } | 2405 } |
2418 | 2406 |
2419 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { | 2407 ScopedTraceBinaryEfficient::~ScopedTraceBinaryEfficient() { |
2420 if (*category_group_enabled_) { | 2408 if (*category_group_enabled_) { |
2421 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, | 2409 TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled_, |
2422 name_, event_handle_); | 2410 name_, event_handle_); |
2423 } | 2411 } |
2424 } | 2412 } |
2425 | 2413 |
2426 } // namespace trace_event_internal | 2414 } // namespace trace_event_internal |
OLD | NEW |