| 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 |