| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/activity_tracker.h" | 5 #include "base/debug/activity_tracker.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <limits> | 8 #include <limits> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 // arbitrary but happens to be the first 4 bytes of SHA1(ThreadActivityTracker). | 34 // arbitrary but happens to be the first 4 bytes of SHA1(ThreadActivityTracker). |
| 35 // A version number is added on so that major structure changes won't try to | 35 // A version number is added on so that major structure changes won't try to |
| 36 // read an older version (since the cookie won't match). | 36 // read an older version (since the cookie won't match). |
| 37 const uint32_t kHeaderCookie = 0xC0029B24UL + 2; // v2 | 37 const uint32_t kHeaderCookie = 0xC0029B24UL + 2; // v2 |
| 38 | 38 |
| 39 // The minimum depth a stack should support. | 39 // The minimum depth a stack should support. |
| 40 const int kMinStackDepth = 2; | 40 const int kMinStackDepth = 2; |
| 41 | 41 |
| 42 // The amount of memory set aside for holding arbitrary user data (key/value | 42 // The amount of memory set aside for holding arbitrary user data (key/value |
| 43 // pairs) globally or associated with ActivityData entries. | 43 // pairs) globally or associated with ActivityData entries. |
| 44 const size_t kUserDataSize = 1024; // bytes | 44 const size_t kUserDataSize = 1 << 10; // 1 KiB |
| 45 const size_t kGlobalDataSize = 4096; // bytes | 45 const size_t kGlobalDataSize = 16 << 10; // 16 KiB |
| 46 const size_t kMaxUserDataNameLength = | 46 const size_t kMaxUserDataNameLength = |
| 47 static_cast<size_t>(std::numeric_limits<uint8_t>::max()); | 47 static_cast<size_t>(std::numeric_limits<uint8_t>::max()); |
| 48 | 48 |
| 49 // A constant used to indicate that module information is changing. | 49 // A constant used to indicate that module information is changing. |
| 50 const uint32_t kModuleInformationChanging = 0x80000000; | 50 const uint32_t kModuleInformationChanging = 0x80000000; |
| 51 | 51 |
| 52 union ThreadRef { | 52 union ThreadRef { |
| 53 int64_t as_id; | 53 int64_t as_id; |
| 54 #if defined(OS_WIN) | 54 #if defined(OS_WIN) |
| 55 // On Windows, the handle itself is often a pseudo-handle with a common | 55 // On Windows, the handle itself is often a pseudo-handle with a common |
| (...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 // to be used for analysis through snapshots. | 281 // to be used for analysis through snapshots. |
| 282 ImportExistingData(); | 282 ImportExistingData(); |
| 283 } | 283 } |
| 284 | 284 |
| 285 ActivityUserData::~ActivityUserData() {} | 285 ActivityUserData::~ActivityUserData() {} |
| 286 | 286 |
| 287 void ActivityUserData::Set(StringPiece name, | 287 void ActivityUserData::Set(StringPiece name, |
| 288 ValueType type, | 288 ValueType type, |
| 289 const void* memory, | 289 const void* memory, |
| 290 size_t size) { | 290 size_t size) { |
| 291 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 292 DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length()); | 291 DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length()); |
| 293 size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1), | 292 size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1), |
| 294 size); | 293 size); |
| 295 | 294 |
| 296 // It's possible that no user data is being stored. | 295 // It's possible that no user data is being stored. |
| 297 if (!memory_) | 296 if (!memory_) |
| 298 return; | 297 return; |
| 299 | 298 |
| 300 // The storage of a name is limited so use that limit during lookup. | 299 // The storage of a name is limited so use that limit during lookup. |
| 301 if (name.length() > kMaxUserDataNameLength) | 300 if (name.length() > kMaxUserDataNameLength) |
| (...skipping 747 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1049 AutoLock lock(global->user_data_allocator_lock_); | 1048 AutoLock lock(global->user_data_allocator_lock_); |
| 1050 user_data_ = | 1049 user_data_ = |
| 1051 tracker_->GetUserData(activity_id_, &global->user_data_allocator_); | 1050 tracker_->GetUserData(activity_id_, &global->user_data_allocator_); |
| 1052 } else { | 1051 } else { |
| 1053 user_data_ = MakeUnique<ActivityUserData>(nullptr, 0); | 1052 user_data_ = MakeUnique<ActivityUserData>(nullptr, 0); |
| 1054 } | 1053 } |
| 1055 } | 1054 } |
| 1056 return *user_data_; | 1055 return *user_data_; |
| 1057 } | 1056 } |
| 1058 | 1057 |
| 1058 GlobalActivityTracker::GlobalUserData::GlobalUserData(void* memory, size_t size) |
| 1059 : ActivityUserData(memory, size) {} |
| 1060 |
| 1061 GlobalActivityTracker::GlobalUserData::~GlobalUserData() {} |
| 1062 |
| 1063 void GlobalActivityTracker::GlobalUserData::Set(StringPiece name, |
| 1064 ValueType type, |
| 1065 const void* memory, |
| 1066 size_t size) { |
| 1067 AutoLock lock(data_lock_); |
| 1068 ActivityUserData::Set(name, type, memory, size); |
| 1069 } |
| 1070 |
| 1059 GlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker( | 1071 GlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker( |
| 1060 PersistentMemoryAllocator::Reference mem_reference, | 1072 PersistentMemoryAllocator::Reference mem_reference, |
| 1061 void* base, | 1073 void* base, |
| 1062 size_t size) | 1074 size_t size) |
| 1063 : ThreadActivityTracker(base, size), | 1075 : ThreadActivityTracker(base, size), |
| 1064 mem_reference_(mem_reference), | 1076 mem_reference_(mem_reference), |
| 1065 mem_base_(base) {} | 1077 mem_base_(base) {} |
| 1066 | 1078 |
| 1067 GlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() { | 1079 GlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() { |
| 1068 // The global |g_tracker_| must point to the owner of this class since all | 1080 // The global |g_tracker_| must point to the owner of this class since all |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 allocator_->AllocateObject<ModuleInfoRecord>(required_size); | 1221 allocator_->AllocateObject<ModuleInfoRecord>(required_size); |
| 1210 if (!record) | 1222 if (!record) |
| 1211 return; | 1223 return; |
| 1212 | 1224 |
| 1213 bool success = record->EncodeFrom(info, required_size); | 1225 bool success = record->EncodeFrom(info, required_size); |
| 1214 DCHECK(success); | 1226 DCHECK(success); |
| 1215 allocator_->MakeIterable(record); | 1227 allocator_->MakeIterable(record); |
| 1216 modules_.insert(std::make_pair(info.file, record)); | 1228 modules_.insert(std::make_pair(info.file, record)); |
| 1217 } | 1229 } |
| 1218 | 1230 |
| 1231 void GlobalActivityTracker::RecordFieldTrial(const std::string& trial_name, |
| 1232 StringPiece group_name) { |
| 1233 const std::string key = std::string("FieldTrial.") + trial_name; |
| 1234 global_data_.SetString(key, group_name); |
| 1235 } |
| 1236 |
| 1219 GlobalActivityTracker::GlobalActivityTracker( | 1237 GlobalActivityTracker::GlobalActivityTracker( |
| 1220 std::unique_ptr<PersistentMemoryAllocator> allocator, | 1238 std::unique_ptr<PersistentMemoryAllocator> allocator, |
| 1221 int stack_depth) | 1239 int stack_depth) |
| 1222 : allocator_(std::move(allocator)), | 1240 : allocator_(std::move(allocator)), |
| 1223 stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)), | 1241 stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)), |
| 1224 this_thread_tracker_(&OnTLSDestroy), | 1242 this_thread_tracker_(&OnTLSDestroy), |
| 1225 thread_tracker_count_(0), | 1243 thread_tracker_count_(0), |
| 1226 thread_tracker_allocator_(allocator_.get(), | 1244 thread_tracker_allocator_(allocator_.get(), |
| 1227 kTypeIdActivityTracker, | 1245 kTypeIdActivityTracker, |
| 1228 kTypeIdActivityTrackerFree, | 1246 kTypeIdActivityTrackerFree, |
| 1229 stack_memory_size_, | 1247 stack_memory_size_, |
| 1230 kCachedThreadMemories, | 1248 kCachedThreadMemories, |
| 1231 /*make_iterable=*/true), | 1249 /*make_iterable=*/true), |
| 1232 user_data_allocator_(allocator_.get(), | 1250 user_data_allocator_(allocator_.get(), |
| 1233 kTypeIdUserDataRecord, | 1251 kTypeIdUserDataRecord, |
| 1234 kTypeIdUserDataRecordFree, | 1252 kTypeIdUserDataRecordFree, |
| 1235 kUserDataSize, | 1253 kUserDataSize, |
| 1236 kCachedUserDataMemories, | 1254 kCachedUserDataMemories, |
| 1237 /*make_iterable=*/false), | 1255 /*make_iterable=*/false), |
| 1238 user_data_( | 1256 global_data_( |
| 1239 allocator_->GetAsArray<char>( | 1257 allocator_->GetAsArray<char>( |
| 1240 allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord), | 1258 allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord), |
| 1241 kTypeIdGlobalDataRecord, | 1259 kTypeIdGlobalDataRecord, |
| 1242 PersistentMemoryAllocator::kSizeAny), | 1260 PersistentMemoryAllocator::kSizeAny), |
| 1243 kGlobalDataSize) { | 1261 kGlobalDataSize) { |
| 1244 // Ensure the passed memory is valid and empty (iterator finds nothing). | 1262 // Ensure the passed memory is valid and empty (iterator finds nothing). |
| 1245 uint32_t type; | 1263 uint32_t type; |
| 1246 DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type)); | 1264 DCHECK(!PersistentMemoryAllocator::Iterator(allocator_.get()).GetNext(&type)); |
| 1247 | 1265 |
| 1248 // Ensure that there is no other global object and then make this one such. | 1266 // Ensure that there is no other global object and then make this one such. |
| 1249 DCHECK(!g_tracker_); | 1267 DCHECK(!g_tracker_); |
| 1250 subtle::NoBarrier_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this)); | 1268 subtle::NoBarrier_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this)); |
| 1251 | 1269 |
| 1252 // The global records must be iterable in order to be found by an analyzer. | 1270 // The global records must be iterable in order to be found by an analyzer. |
| 1253 allocator_->MakeIterable(allocator_->GetAsReference( | 1271 allocator_->MakeIterable(allocator_->GetAsReference( |
| 1254 user_data_.GetBaseAddress(), kTypeIdGlobalDataRecord)); | 1272 global_data_.GetBaseAddress(), kTypeIdGlobalDataRecord)); |
| 1273 |
| 1274 // Fetch and record all activated field trials. |
| 1275 FieldTrial::ActiveGroups active_groups; |
| 1276 FieldTrialList::GetActiveFieldTrialGroups(&active_groups); |
| 1277 for (auto& group : active_groups) |
| 1278 RecordFieldTrial(group.trial_name, group.group_name); |
| 1255 } | 1279 } |
| 1256 | 1280 |
| 1257 GlobalActivityTracker::~GlobalActivityTracker() { | 1281 GlobalActivityTracker::~GlobalActivityTracker() { |
| 1258 DCHECK_EQ(Get(), this); | 1282 DCHECK_EQ(Get(), this); |
| 1259 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed)); | 1283 DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed)); |
| 1260 subtle::NoBarrier_Store(&g_tracker_, 0); | 1284 subtle::NoBarrier_Store(&g_tracker_, 0); |
| 1261 } | 1285 } |
| 1262 | 1286 |
| 1263 void GlobalActivityTracker::ReturnTrackerMemory( | 1287 void GlobalActivityTracker::ReturnTrackerMemory( |
| 1264 ManagedActivityTracker* tracker) { | 1288 ManagedActivityTracker* tracker) { |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1359 : GlobalActivityTracker::ScopedThreadActivity( | 1383 : GlobalActivityTracker::ScopedThreadActivity( |
| 1360 program_counter, | 1384 program_counter, |
| 1361 nullptr, | 1385 nullptr, |
| 1362 Activity::ACT_PROCESS_WAIT, | 1386 Activity::ACT_PROCESS_WAIT, |
| 1363 ActivityData::ForProcess(process->Pid()), | 1387 ActivityData::ForProcess(process->Pid()), |
| 1364 /*lock_allowed=*/true) {} | 1388 /*lock_allowed=*/true) {} |
| 1365 #endif | 1389 #endif |
| 1366 | 1390 |
| 1367 } // namespace debug | 1391 } // namespace debug |
| 1368 } // namespace base | 1392 } // namespace base |
| OLD | NEW |