136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Copyright 2016 The Chromium Authors. All rights reserved. 236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Use of this source code is governed by a BSD-style license that can be 336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// found in the LICENSE file. 436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/debug/activity_tracker.h" 636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include <algorithm> 836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include <limits> 936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include <utility> 1036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/atomic_sequence_num.h" 1236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/debug/stack_trace.h" 1336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/files/file.h" 1436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/files/file_path.h" 1536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/files/memory_mapped_file.h" 1636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/logging.h" 1736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/memory/ptr_util.h" 1836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/metrics/field_trial.h" 1936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/metrics/histogram_macros.h" 2036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/pending_task.h" 2136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/pickle.h" 2236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/process/process.h" 2336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/process/process_handle.h" 2436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/stl_util.h" 2536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/strings/string_util.h" 26319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#include "base/strings/utf_string_conversions.h" 2736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#include "base/threading/platform_thread.h" 2836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 2936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abenamespace base { 3036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abenamespace debug { 3136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 3236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abenamespace { 3336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 3436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The minimum depth a stack should support. 3536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst int kMinStackDepth = 2; 3636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 3736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The amount of memory set aside for holding arbitrary user data (key/value 3836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// pairs) globally or associated with ActivityData entries. 3936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst size_t kUserDataSize = 1 << 10; // 1 KiB 40319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst size_t kProcessDataSize = 4 << 10; // 4 KiB 4136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst size_t kGlobalDataSize = 16 << 10; // 16 KiB 4236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst size_t kMaxUserDataNameLength = 4336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe static_cast<size_t>(std::numeric_limits<uint8_t>::max()); 4436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 4536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// A constant used to indicate that module information is changing. 4636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst uint32_t kModuleInformationChanging = 0x80000000; 4736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 48319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// The key used to record process information. 49319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst char kProcessPhaseDataKey[] = "process-phase"; 50319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 51319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// An atomically incrementing number, used to check for recreations of objects 52319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// in the same memory space. 53319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiStaticAtomicSequenceNumber g_next_id; 54319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 5536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeunion ThreadRef { 5636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe int64_t as_id; 5736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_WIN) 5836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // On Windows, the handle itself is often a pseudo-handle with a common 5936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // value meaning "this thread" and so the thread-id is used. The former 6036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // can be converted to a thread-id with a system call. 6136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PlatformThreadId as_tid; 6236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#elif defined(OS_POSIX) 6336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // On Posix, the handle is always a unique identifier so no conversion 6436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // needs to be done. However, it's value is officially opaque so there 6536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // is no one correct way to convert it to a numerical identifier. 6636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PlatformThreadHandle::Handle as_handle; 6736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 6836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}; 6936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 70f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// Gets the next non-zero identifier. It is only unique within a process. 71319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiuint32_t GetNextDataId() { 72319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t id; 73319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski while ((id = g_next_id.GetNext()) == 0) 74319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ; 75319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return id; 76319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 77319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 78f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// Gets the current process-id, either from the GlobalActivityTracker if it 79f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// exists (where the PID can be defined for testing) or from the system if 80f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// there isn't such. 81f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abeint64_t GetProcessId() { 82f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe GlobalActivityTracker* global = GlobalActivityTracker::Get(); 83f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe if (global) 84f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe return global->process_id(); 85f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe return GetCurrentProcId(); 86f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe} 87f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 88319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// Finds and reuses a specific allocation or creates a new one. 89319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiPersistentMemoryAllocator::Reference AllocateFrom( 90319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski PersistentMemoryAllocator* allocator, 91319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t from_type, 92319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski size_t size, 93319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t to_type) { 94319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski PersistentMemoryAllocator::Iterator iter(allocator); 95319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski PersistentMemoryAllocator::Reference ref; 96319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski while ((ref = iter.GetNextOfType(from_type)) != 0) { 97319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_LE(size, allocator->GetAllocSize(ref)); 98319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // This can fail if a another thread has just taken it. It is assumed that 99319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // the memory is cleared during the "free" operation. 100319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (allocator->ChangeType(ref, to_type, from_type, /*clear=*/false)) 101319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return ref; 102319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 103319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 104319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return allocator->Allocate(size, to_type); 105319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 106319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 10736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Determines the previous aligned index. 10836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t RoundDownToAlignment(size_t index, size_t alignment) { 10936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return index & (0 - alignment); 11036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 11136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 11236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// Determines the next aligned index. 11336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t RoundUpToAlignment(size_t index, size_t alignment) { 11436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return (index + (alignment - 1)) & (0 - alignment); 11536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 11636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 117319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// Converts "tick" timing into wall time. 118319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiTime WallTimeFromTickTime(int64_t ticks_start, int64_t ticks, Time time_start) { 119319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return time_start + TimeDelta::FromInternalValue(ticks - ticks_start); 120319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 121319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 12236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} // namespace 12336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 124319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiOwningProcess::OwningProcess() {} 125319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiOwningProcess::~OwningProcess() {} 126319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 127f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid OwningProcess::Release_Initialize(int64_t pid) { 128319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t old_id = data_id.load(std::memory_order_acquire); 129319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_EQ(0U, old_id); 130f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe process_id = pid != 0 ? pid : GetProcessId(); 131319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski create_stamp = Time::Now().ToInternalValue(); 132319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski data_id.store(GetNextDataId(), std::memory_order_release); 133319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 134319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 135f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid OwningProcess::SetOwningProcessIdForTesting(int64_t pid, int64_t stamp) { 136319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_NE(0U, data_id); 137319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_id = pid; 138319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski create_stamp = stamp; 139319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 140319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 141319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// static 142319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool OwningProcess::GetOwningProcessId(const void* memory, 143f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t* out_id, 144319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t* out_stamp) { 145319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const OwningProcess* info = reinterpret_cast<const OwningProcess*>(memory); 146319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t id = info->data_id.load(std::memory_order_acquire); 147319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (id == 0) 148319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return false; 149319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 150f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe *out_id = info->process_id; 151319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski *out_stamp = info->create_stamp; 152319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return id == info->data_id.load(std::memory_order_seq_cst); 153319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 15436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 15536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// It doesn't matter what is contained in this (though it will be all zeros) 15636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// as only the address of it is important. 15736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeconst ActivityData kNullActivityData = {}; 15836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 15936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityData ActivityData::ForThread(const PlatformThreadHandle& handle) { 16036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ThreadRef thread_ref; 16136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_ref.as_id = 0; // Zero the union in case other is smaller. 16236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_WIN) 16336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_ref.as_tid = ::GetThreadId(handle.platform_handle()); 16436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#elif defined(OS_POSIX) 16536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_ref.as_handle = handle.platform_handle(); 16636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 16736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return ForThread(thread_ref.as_id); 16836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 16936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 17036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::ActivityTrackerMemoryAllocator( 17136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PersistentMemoryAllocator* allocator, 17236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t object_type, 17336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t object_free_type, 17436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t object_size, 17536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t cache_size, 17636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe bool make_iterable) 17736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : allocator_(allocator), 17836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe object_type_(object_type), 17936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe object_free_type_(object_free_type), 18036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe object_size_(object_size), 18136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe cache_size_(cache_size), 18236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe make_iterable_(make_iterable), 18336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe iterator_(allocator), 18436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe cache_values_(new Reference[cache_size]), 18536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe cache_used_(0) { 18636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(allocator); 18736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 18836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 18936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::~ActivityTrackerMemoryAllocator() {} 19036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 19136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::Reference 19236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityTrackerMemoryAllocator::GetObjectReference() { 19336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // First see if there is a cached value that can be returned. This is much 19436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // faster than searching the memory system for free blocks. 19536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe while (cache_used_ > 0) { 19636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Reference cached = cache_values_[--cache_used_]; 19736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Change the type of the cached object to the proper type and return it. 19836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // If the type-change fails that means another thread has taken this from 19936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // under us (via the search below) so ignore it and keep trying. Don't 20036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // clear the memory because that was done when the type was made "free". 20136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (allocator_->ChangeType(cached, object_type_, object_free_type_, false)) 20236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return cached; 20336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 20436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 20536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Fetch the next "free" object from persistent memory. Rather than restart 20636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // the iterator at the head each time and likely waste time going again 20736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // through objects that aren't relevant, the iterator continues from where 20836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // it last left off and is only reset when the end is reached. If the 20936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // returned reference matches |last|, then it has wrapped without finding 21036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // anything. 21136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const Reference last = iterator_.GetLast(); 21236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe while (true) { 21336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t type; 21436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Reference found = iterator_.GetNext(&type); 21536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (found && type == object_free_type_) { 21636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Found a free object. Change it to the proper type and return it. If 21736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // the type-change fails that means another thread has taken this from 21836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // under us so ignore it and keep trying. 21936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (allocator_->ChangeType(found, object_type_, object_free_type_, false)) 22036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return found; 22136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 22236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (found == last) { 22336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Wrapped. No desired object was found. 22436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe break; 22536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 22636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!found) { 22736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Reached end; start over at the beginning. 22836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe iterator_.Reset(); 22936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 23036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 23136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 23236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // No free block was found so instead allocate a new one. 23336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Reference allocated = allocator_->Allocate(object_size_, object_type_); 23436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (allocated && make_iterable_) 23536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->MakeIterable(allocated); 23636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return allocated; 23736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 23836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 23936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityTrackerMemoryAllocator::ReleaseObjectReference(Reference ref) { 24036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Mark object as free. 24136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe bool success = allocator_->ChangeType(ref, object_free_type_, object_type_, 24236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*clear=*/true); 24336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(success); 24436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 24536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Add this reference to our "free" cache if there is space. If not, the type 24636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // has still been changed to indicate that it is free so this (or another) 24736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // thread can find it, albeit more slowly, using the iteration method above. 24836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (cache_used_ < cache_size_) 24936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe cache_values_[cache_used_++] = ref; 25036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 25136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 25236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static 25336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid Activity::FillFrom(Activity* activity, 25436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 25536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* origin, 25636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Type type, 25736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const ActivityData& data) { 25836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->time_internal = base::TimeTicks::Now().ToInternalValue(); 25936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->calling_address = reinterpret_cast<uintptr_t>(program_counter); 26036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->origin_address = reinterpret_cast<uintptr_t>(origin); 26136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->activity_type = type; 26236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->data = data; 26336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 26436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(SYZYASAN) 26536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Create a stacktrace from the current location and get the addresses. 26636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe StackTrace stack_trace; 26736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t stack_depth; 26836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* const* stack_addrs = stack_trace.Addresses(&stack_depth); 26936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Copy the stack addresses, ignoring the first one (here). 27036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t i; 27136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe for (i = 1; i < stack_depth && i < kActivityCallStackSize; ++i) { 27236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->call_stack[i - 1] = reinterpret_cast<uintptr_t>(stack_addrs[i]); 27336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 27436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->call_stack[i - 1] = 0; 27536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#else 27636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->call_stack[0] = 0; 27736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 27836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 27936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 28036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::TypedValue::TypedValue() {} 28136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::TypedValue::TypedValue(const TypedValue& other) = default; 28236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::TypedValue::~TypedValue() {} 28336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 28436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::Get() const { 28536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(RAW_VALUE, type_); 28636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return long_value_; 28736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 28836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 28936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::GetString() const { 29036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(STRING_VALUE, type_); 29136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return long_value_; 29236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 29336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 29436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ActivityUserData::TypedValue::GetBool() const { 29536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(BOOL_VALUE, type_); 29636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return short_value_ != 0; 29736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 29836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 29936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abechar ActivityUserData::TypedValue::GetChar() const { 30036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(CHAR_VALUE, type_); 30136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return static_cast<char>(short_value_); 30236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 30336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 30436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeint64_t ActivityUserData::TypedValue::GetInt() const { 30536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(SIGNED_VALUE, type_); 30636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return static_cast<int64_t>(short_value_); 30736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 30836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 30936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abeuint64_t ActivityUserData::TypedValue::GetUint() const { 31036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(UNSIGNED_VALUE, type_); 31136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return static_cast<uint64_t>(short_value_); 31236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 31336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 31436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::GetReference() const { 31536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(RAW_VALUE_REFERENCE, type_); 31636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return ref_value_; 31736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 31836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 31936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeStringPiece ActivityUserData::TypedValue::GetStringReference() const { 32036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(STRING_VALUE_REFERENCE, type_); 32136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return ref_value_; 32236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 32336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 324319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// These are required because std::atomic is (currently) not a POD type and 325319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// thus clang requires explicit out-of-line constructors and destructors even 326319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// when they do nothing. 32736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::ValueInfo::ValueInfo() {} 32836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::ValueInfo::ValueInfo(ValueInfo&&) = default; 32936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::ValueInfo::~ValueInfo() {} 330319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::MemoryHeader::MemoryHeader() {} 331319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::MemoryHeader::~MemoryHeader() {} 332319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::FieldHeader::FieldHeader() {} 333319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiActivityUserData::FieldHeader::~FieldHeader() {} 33436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 335f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko AbeActivityUserData::ActivityUserData() : ActivityUserData(nullptr, 0, -1) {} 33636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 337f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko AbeActivityUserData::ActivityUserData(void* memory, size_t size, int64_t pid) 33836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : memory_(reinterpret_cast<char*>(memory)), 33936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe available_(RoundDownToAlignment(size, kMemoryAlignment)), 340f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe header_(reinterpret_cast<MemoryHeader*>(memory)), 341f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe orig_data_id(0), 342f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe orig_process_id(0), 343f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe orig_create_stamp(0) { 34436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // It's possible that no user data is being stored. 34536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!memory_) 34636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 34736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 348319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski static_assert(0 == sizeof(MemoryHeader) % kMemoryAlignment, "invalid header"); 349319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_LT(sizeof(MemoryHeader), available_); 350319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (header_->owner.data_id.load(std::memory_order_acquire) == 0) 351f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe header_->owner.Release_Initialize(pid); 352319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski memory_ += sizeof(MemoryHeader); 353319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski available_ -= sizeof(MemoryHeader); 35436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 355f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // Make a copy of identifying information for later comparison. 356f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe *const_cast<uint32_t*>(&orig_data_id) = 357f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe header_->owner.data_id.load(std::memory_order_acquire); 358f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe *const_cast<int64_t*>(&orig_process_id) = header_->owner.process_id; 359f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe *const_cast<int64_t*>(&orig_create_stamp) = header_->owner.create_stamp; 360f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 36136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // If there is already data present, load that. This allows the same class 36236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // to be used for analysis through snapshots. 36336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ImportExistingData(); 36436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 36536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 36636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData::~ActivityUserData() {} 36736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 368319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool ActivityUserData::CreateSnapshot(Snapshot* output_snapshot) const { 369319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK(output_snapshot); 370319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK(output_snapshot->empty()); 371319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 372319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Find any new data that may have been added by an active instance of this 373319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // class that is adding records. 374319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ImportExistingData(); 375319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 376f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // Add all the values to the snapshot. 377319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski for (const auto& entry : values_) { 378319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski TypedValue value; 379f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe const size_t size = entry.second.size_ptr->load(std::memory_order_acquire); 380319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski value.type_ = entry.second.type; 381f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK_GE(entry.second.extent, size); 382319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 383319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski switch (entry.second.type) { 384319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case RAW_VALUE: 385319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case STRING_VALUE: 386319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski value.long_value_ = 387f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe std::string(reinterpret_cast<char*>(entry.second.memory), size); 388319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski break; 389319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case RAW_VALUE_REFERENCE: 390319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case STRING_VALUE_REFERENCE: { 391319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ReferenceRecord* ref = 392319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski reinterpret_cast<ReferenceRecord*>(entry.second.memory); 393319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski value.ref_value_ = StringPiece( 394319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski reinterpret_cast<char*>(static_cast<uintptr_t>(ref->address)), 395319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski static_cast<size_t>(ref->size)); 396319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } break; 397319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case BOOL_VALUE: 398319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case CHAR_VALUE: 399319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski value.short_value_ = *reinterpret_cast<char*>(entry.second.memory); 400319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski break; 401319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case SIGNED_VALUE: 402319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case UNSIGNED_VALUE: 403319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski value.short_value_ = *reinterpret_cast<uint64_t*>(entry.second.memory); 404319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski break; 405319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case END_OF_VALUES: // Included for completeness purposes. 406319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski NOTREACHED(); 407319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 408319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski auto inserted = output_snapshot->insert( 409319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski std::make_pair(entry.second.name.as_string(), std::move(value))); 410319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK(inserted.second); // True if inserted, false if existed. 411319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 412319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 413f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // Another import attempt will validate that the underlying memory has not 414f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // been reused for another purpose. Entries added since the first import 415f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // will be ignored here but will be returned if another snapshot is created. 416f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe ImportExistingData(); 417f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe if (!memory_) { 418f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe output_snapshot->clear(); 419f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe return false; 420f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe } 421f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 422f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // Successful snapshot. 423319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return true; 424319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 425319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 426319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst void* ActivityUserData::GetBaseAddress() const { 427319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The |memory_| pointer advances as elements are written but the |header_| 428319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // value is always at the start of the block so just return that. 429319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return header_; 430319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 431319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 432f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid ActivityUserData::SetOwningProcessIdForTesting(int64_t pid, 433319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t stamp) { 434319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (!header_) 435319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return; 436319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->owner.SetOwningProcessIdForTesting(pid, stamp); 437319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 438319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 439319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// static 440319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool ActivityUserData::GetOwningProcessId(const void* memory, 441f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t* out_id, 442319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t* out_stamp) { 443319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const MemoryHeader* header = reinterpret_cast<const MemoryHeader*>(memory); 444319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp); 445319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 446319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 44736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityUserData::Set(StringPiece name, 44836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ValueType type, 44936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* memory, 45036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t size) { 45136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_GE(std::numeric_limits<uint8_t>::max(), name.length()); 45236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size = std::min(std::numeric_limits<uint16_t>::max() - (kMemoryAlignment - 1), 45336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size); 45436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 45536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // It's possible that no user data is being stored. 45636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!memory_) 45736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 45836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 45936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The storage of a name is limited so use that limit during lookup. 46036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (name.length() > kMaxUserDataNameLength) 46136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe name.set(name.data(), kMaxUserDataNameLength); 46236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 46336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ValueInfo* info; 46436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe auto existing = values_.find(name); 46536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (existing != values_.end()) { 46636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info = &existing->second; 46736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } else { 46836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The name size is limited to what can be held in a single byte but 46936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // because there are not alignment constraints on strings, it's set tight 47036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // against the header. Its extent (the reserved space, even if it's not 47136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // all used) is calculated so that, when pressed against the header, the 47236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // following field will be aligned properly. 47336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t name_size = name.length(); 47436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t name_extent = 475319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski RoundUpToAlignment(sizeof(FieldHeader) + name_size, kMemoryAlignment) - 476319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski sizeof(FieldHeader); 47736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t value_extent = RoundUpToAlignment(size, kMemoryAlignment); 47836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 47936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The "base size" is the size of the header and (padded) string key. Stop 48036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // now if there's not room enough for even this. 481319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski size_t base_size = sizeof(FieldHeader) + name_extent; 48236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (base_size > available_) 48336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 48436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 48536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The "full size" is the size for storing the entire value. 48636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t full_size = std::min(base_size + value_extent, available_); 48736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 48836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // If the value is actually a single byte, see if it can be stuffed at the 48936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // end of the name extent rather than wasting kMemoryAlignment bytes. 49036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (size == 1 && name_extent > name_size) { 49136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe full_size = base_size; 49236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe --name_extent; 49336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe --base_size; 49436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 49536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 49636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Truncate the stored size to the amount of available memory. Stop now if 49736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // there's not any room for even part of the value. 49836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (size != 0) { 49936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size = std::min(full_size - base_size, size); 50036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (size == 0) 50136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 50236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 50336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 50436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Allocate a chunk of memory. 505319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_); 50636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memory_ += full_size; 50736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe available_ -= full_size; 50836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 50936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Datafill the header and name records. Memory must be zeroed. The |type| 51036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // is written last, atomically, to release all the other values. 51136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(END_OF_VALUES, header->type.load(std::memory_order_relaxed)); 51236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, header->value_size.load(std::memory_order_relaxed)); 51336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header->name_size = static_cast<uint8_t>(name_size); 51436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header->record_size = full_size; 515319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski char* name_memory = reinterpret_cast<char*>(header) + sizeof(FieldHeader); 51636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe void* value_memory = 517319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski reinterpret_cast<char*>(header) + sizeof(FieldHeader) + name_extent; 51836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memcpy(name_memory, name.data(), name_size); 51936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header->type.store(type, std::memory_order_release); 52036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 52136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Create an entry in |values_| so that this field can be found and changed 52236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // later on without having to allocate new entries. 52336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe StringPiece persistent_name(name_memory, name_size); 52436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe auto inserted = 52536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe values_.insert(std::make_pair(persistent_name, ValueInfo())); 52636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(inserted.second); // True if inserted, false if existed. 52736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info = &inserted.first->second; 52836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->name = persistent_name; 52936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->memory = value_memory; 53036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->size_ptr = &header->value_size; 531319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski info->extent = full_size - sizeof(FieldHeader) - name_extent; 53236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->type = type; 53336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 53436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 53536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Copy the value data to storage. The |size| is written last, atomically, to 53636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // release the copied data. Until then, a parallel reader will just ignore 53736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // records with a zero size. 53836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(type, info->type); 53936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size = std::min(size, info->extent); 54036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->size_ptr->store(0, std::memory_order_seq_cst); 54136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memcpy(info->memory, memory, size); 54236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->size_ptr->store(size, std::memory_order_release); 54336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 54436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 54536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityUserData::SetReference(StringPiece name, 54636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ValueType type, 54736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* memory, 54836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t size) { 54936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ReferenceRecord rec; 55036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe rec.address = reinterpret_cast<uintptr_t>(memory); 55136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe rec.size = size; 55236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Set(name, type, &rec, sizeof(rec)); 55336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 55436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 55536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ActivityUserData::ImportExistingData() const { 556f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // It's possible that no user data is being stored. 557f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe if (!memory_) 558f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe return; 559f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 560319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski while (available_ > sizeof(FieldHeader)) { 561319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski FieldHeader* header = reinterpret_cast<FieldHeader*>(memory_); 56236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ValueType type = 56336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe static_cast<ValueType>(header->type.load(std::memory_order_acquire)); 56436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (type == END_OF_VALUES) 56536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 56636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (header->record_size > available_) 56736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 56836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 569319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski size_t value_offset = RoundUpToAlignment( 570319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski sizeof(FieldHeader) + header->name_size, kMemoryAlignment); 57136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (header->record_size == value_offset && 57236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header->value_size.load(std::memory_order_relaxed) == 1) { 57336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe value_offset -= 1; 57436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 57536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (value_offset + header->value_size > header->record_size) 57636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 57736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 57836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ValueInfo info; 579319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski info.name = StringPiece(memory_ + sizeof(FieldHeader), header->name_size); 58036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info.type = type; 58136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info.memory = memory_ + value_offset; 58236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info.size_ptr = &header->value_size; 58336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info.extent = header->record_size - value_offset; 58436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 58536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe StringPiece key(info.name); 58636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe values_.insert(std::make_pair(key, std::move(info))); 58736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 58836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memory_ += header->record_size; 58936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe available_ -= header->record_size; 59036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 591f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 592f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // Check if memory has been completely reused. 593f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe if (header_->owner.data_id.load(std::memory_order_acquire) != orig_data_id || 594f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe header_->owner.process_id != orig_process_id || 595f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe header_->owner.create_stamp != orig_create_stamp) { 596f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe memory_ = nullptr; 597f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe values_.clear(); 598f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe } 59970cd4fac31a9b0865dab6574540f70cc103337dcJakub Pawlowski} 60070cd4fac31a9b0865dab6574540f70cc103337dcJakub Pawlowski 60136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// This information is kept for every thread that is tracked. It is filled 60236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// the very first time the thread is seen. All fields must be of exact sizes 60336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// so there is no issue moving between 32 and 64-bit builds. 60436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abestruct ThreadActivityTracker::Header { 60536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Defined in .h for analyzer access. Increment this if structure changes! 60636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe static constexpr uint32_t kPersistentTypeId = 60736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe GlobalActivityTracker::kTypeIdActivityTracker; 60836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 60936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Expected size for 32/64-bit check. 610319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski static constexpr size_t kExpectedInstanceSize = 611319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski OwningProcess::kExpectedInstanceSize + Activity::kExpectedInstanceSize + 612319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 72; 61370cd4fac31a9b0865dab6574540f70cc103337dcJakub Pawlowski 614319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // This information uniquely identifies a process. 615319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski OwningProcess owner; 61636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 617319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The thread-id (thread_ref.as_id) to which this data belongs. This number 618319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // is not guaranteed to mean anything but combined with the process-id from 619319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // OwningProcess is unique among all active trackers. 62036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ThreadRef thread_ref; 62136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 62236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The start-time and start-ticks when the data was created. Each activity 62336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // record has a |time_internal| value that can be converted to a "wall time" 62436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // with these two values. 62536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe int64_t start_time; 62636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe int64_t start_ticks; 62736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 628319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The number of Activity slots (spaces that can hold an Activity) that 629319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // immediately follow this structure in memory. 630319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t stack_slots; 631319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 632319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Some padding to keep everything 64-bit aligned. 633319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t padding; 634319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 63536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The current depth of the stack. This may be greater than the number of 63636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // slots. If the depth exceeds the number of slots, the newest entries 63736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // won't be recorded. 63836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::atomic<uint32_t> current_depth; 63936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 640319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // A memory location used to indicate if changes have been made to the data 64136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // that would invalidate an in-progress read of its contents. The active 64236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // tracker will zero the value whenever something gets popped from the 64336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // stack. A monitoring tracker can write a non-zero value here, copy the 64436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // stack contents, and read the value to know, if it is still non-zero, that 64536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // the contents didn't change while being copied. This can handle concurrent 64636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // snapshot operations only if each snapshot writes a different bit (which 64736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // is not the current implementation so no parallel snapshots allowed). 648319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski std::atomic<uint32_t> data_unchanged; 649319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 650319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The last "exception" activity. This can't be stored on the stack because 651319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // that could get popped as things unwind. 652319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski Activity last_exception; 65336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 65436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The name of the thread (up to a maximum length). Dynamic-length names 65536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // are not practical since the memory has to come from the same persistent 65636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // allocator that holds this structure and to which this object has no 65736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // reference. 65836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe char thread_name[32]; 65936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe}; 66036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 66136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::Snapshot::Snapshot() {} 66236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::Snapshot::~Snapshot() {} 66336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 66436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ScopedActivity::ScopedActivity( 66536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ThreadActivityTracker* tracker, 66636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 66736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* origin, 66836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::Type type, 66936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const ActivityData& data) 67036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : tracker_(tracker) { 67136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (tracker_) 67236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity_id_ = tracker_->PushActivity(program_counter, origin, type, data); 67336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 67436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 67536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ScopedActivity::~ScopedActivity() { 67636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (tracker_) 67736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe tracker_->PopActivity(activity_id_); 67836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 67936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 68036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::ScopedActivity::ChangeTypeAndData( 68136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::Type type, 68236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const ActivityData& data) { 68336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (tracker_) 68436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe tracker_->ChangeActivity(activity_id_, type, data); 68536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 68636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 68736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ThreadActivityTracker(void* base, size_t size) 68836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : header_(static_cast<Header*>(base)), 68936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe stack_(reinterpret_cast<Activity*>(reinterpret_cast<char*>(base) + 69036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe sizeof(Header))), 69136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe stack_slots_( 69236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe static_cast<uint32_t>((size - sizeof(Header)) / sizeof(Activity))) { 69336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(thread_checker_.CalledOnValidThread()); 69436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 69536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Verify the parameters but fail gracefully if they're not valid so that 69636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // production code based on external inputs will not crash. IsValid() will 69736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // return false in this case. 69836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!base || 69936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Ensure there is enough space for the header and at least a few records. 70036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size < sizeof(Header) + kMinStackDepth * sizeof(Activity) || 70136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Ensure that the |stack_slots_| calculation didn't overflow. 70236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe (size - sizeof(Header)) / sizeof(Activity) > 70336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::numeric_limits<uint32_t>::max()) { 70436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe NOTREACHED(); 70536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 70636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 70736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 70836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Ensure that the thread reference doesn't exceed the size of the ID number. 70936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // This won't compile at the global scope because Header is a private struct. 71036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe static_assert( 71136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe sizeof(header_->thread_ref) == sizeof(header_->thread_ref.as_id), 71236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe "PlatformThreadHandle::Handle is too big to hold in 64-bit ID"); 71336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 71436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Ensure that the alignment of Activity.data is properly aligned to a 71536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // 64-bit boundary so there are no interoperability-issues across cpu 71636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // architectures. 71736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe static_assert(offsetof(Activity, data) % sizeof(uint64_t) == 0, 71836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe "ActivityData.data is not 64-bit aligned"); 71936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 72036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Provided memory should either be completely initialized or all zeros. 721319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (header_->owner.data_id.load(std::memory_order_relaxed) == 0) { 72236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // This is a new file. Double-check other fields and then initialize. 723319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_EQ(0, header_->owner.process_id); 724319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_EQ(0, header_->owner.create_stamp); 72536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, header_->thread_ref.as_id); 72636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, header_->start_time); 72736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, header_->start_ticks); 72836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0U, header_->stack_slots); 72936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0U, header_->current_depth.load(std::memory_order_relaxed)); 730319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_EQ(0U, header_->data_unchanged.load(std::memory_order_relaxed)); 73136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, stack_[0].time_internal); 73236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0U, stack_[0].origin_address); 73336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0U, stack_[0].call_stack[0]); 73436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0U, stack_[0].data.task.sequence_id); 73536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 73636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if defined(OS_WIN) 73736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->thread_ref.as_tid = PlatformThread::CurrentId(); 73836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#elif defined(OS_POSIX) 73936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->thread_ref.as_handle = 74036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PlatformThread::CurrentHandle().platform_handle(); 74136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 74236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 74336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->start_time = base::Time::Now().ToInternalValue(); 74436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->start_ticks = base::TimeTicks::Now().ToInternalValue(); 74536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->stack_slots = stack_slots_; 74636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe strlcpy(header_->thread_name, PlatformThread::GetName(), 74736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe sizeof(header_->thread_name)); 74836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 74936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // This is done last so as to guarantee that everything above is "released" 75036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // by the time this value gets written. 751319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->owner.Release_Initialize(); 75236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 75336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe valid_ = true; 75436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(IsValid()); 75536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } else { 75636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // This is a file with existing data. Perform basic consistency checks. 75736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe valid_ = true; 75836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe valid_ = IsValid(); 75936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 76036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 76136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 76236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::~ThreadActivityTracker() {} 76336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 76436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker::ActivityId ThreadActivityTracker::PushActivity( 76536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 76636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* origin, 76736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::Type type, 76836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const ActivityData& data) { 76936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // A thread-checker creates a lock to check the thread-id which means 77036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // re-entry into this code if lock acquisitions are being tracked. 77136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(type == Activity::ACT_LOCK_ACQUIRE || 77236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_checker_.CalledOnValidThread()); 77336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 77436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Get the current depth of the stack. No access to other memory guarded 77536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // by this variable is done here so a "relaxed" load is acceptable. 77636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t depth = header_->current_depth.load(std::memory_order_relaxed); 77736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 77836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Handle the case where the stack depth has exceeded the storage capacity. 77936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Extra entries will be lost leaving only the base of the stack. 78036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (depth >= stack_slots_) { 78136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Since no other threads modify the data, no compare/exchange is needed. 78236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Since no other memory is being modified, a "relaxed" store is acceptable. 78336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->current_depth.store(depth + 1, std::memory_order_relaxed); 78436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return depth; 78536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 78636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 78736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Get a pointer to the next activity and load it. No atomicity is required 78836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // here because the memory is known only to this thread. It will be made 78936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // known to other threads once the depth is incremented. 79036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::FillFrom(&stack_[depth], program_counter, origin, type, data); 79136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 79236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Save the incremented depth. Because this guards |activity| memory filled 79336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // above that may be read by another thread once the recorded depth changes, 79436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // a "release" store is required. 79536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->current_depth.store(depth + 1, std::memory_order_release); 79636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 79736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The current depth is used as the activity ID because it simply identifies 79836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // an entry. Once an entry is pop'd, it's okay to reuse the ID. 79936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return depth; 80036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 80136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 80236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::ChangeActivity(ActivityId id, 80336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::Type type, 80436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const ActivityData& data) { 80536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(thread_checker_.CalledOnValidThread()); 80636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(type != Activity::ACT_NULL || &data != &kNullActivityData); 80736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_LT(id, header_->current_depth.load(std::memory_order_acquire)); 80836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 80936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Update the information if it is being recorded (i.e. within slot limit). 81036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (id < stack_slots_) { 81136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity* activity = &stack_[id]; 81236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 81336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (type != Activity::ACT_NULL) { 81436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(activity->activity_type & Activity::ACT_CATEGORY_MASK, 81536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe type & Activity::ACT_CATEGORY_MASK); 81636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->activity_type = type; 81736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 81836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 81936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (&data != &kNullActivityData) 82036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity->data = data; 82136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 82236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 82336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 82436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::PopActivity(ActivityId id) { 82536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Do an atomic decrement of the depth. No changes to stack entries guarded 82636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // by this variable are done here so a "relaxed" operation is acceptable. 82736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // |depth| will receive the value BEFORE it was modified which means the 82836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // return value must also be decremented. The slot will be "free" after 82936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // this call but since only a single thread can access this object, the 83036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // data will remain valid until this method returns or calls outside. 83136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t depth = 83236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->current_depth.fetch_sub(1, std::memory_order_relaxed) - 1; 83336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 83436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Validate that everything is running correctly. 83536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(id, depth); 83636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 83736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // A thread-checker creates a lock to check the thread-id which means 83836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // re-entry into this code if lock acquisitions are being tracked. 83936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(stack_[depth].activity_type == Activity::ACT_LOCK_ACQUIRE || 84036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_checker_.CalledOnValidThread()); 84136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 84236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The stack has shrunk meaning that some other thread trying to copy the 84336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // contents for reporting purposes could get bad data. That thread would 844319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // have written a non-zero value into |data_unchanged|; clearing it here 84536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // will let that thread detect that something did change. This needs to 84636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // happen after the atomic |depth| operation above so a "release" store 84736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // is required. 848319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->data_unchanged.store(0, std::memory_order_release); 84936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 85036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 85136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abestd::unique_ptr<ActivityUserData> ThreadActivityTracker::GetUserData( 85236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityId id, 85336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityTrackerMemoryAllocator* allocator) { 854319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Don't allow user data for lock acquisition as recursion may occur. 855319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (stack_[id].activity_type == Activity::ACT_LOCK_ACQUIRE) { 856319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski NOTREACHED(); 857319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return MakeUnique<ActivityUserData>(); 8588abac493f652a1835c61e538919820aa77658a39Mathieu Chartier } 859fe2f52931e8e50253d06329d7bf0a4164c7ba580Jakub Pawlowski 860319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // User-data is only stored for activities actually held in the stack. 861319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (id >= stack_slots_) 862319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return MakeUnique<ActivityUserData>(); 863319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 864319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Create and return a real UserData object. 865319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return CreateUserDataForActivity(&stack_[id], allocator); 86636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 86736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 86836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ThreadActivityTracker::HasUserData(ActivityId id) { 86936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // User-data is only stored for activities actually held in the stack. 87036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return (id < stack_slots_ && stack_[id].user_data_ref); 87136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 87236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 87336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ThreadActivityTracker::ReleaseUserData( 87436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityId id, 87536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityTrackerMemoryAllocator* allocator) { 87636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // User-data is only stored for activities actually held in the stack. 87736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (id < stack_slots_ && stack_[id].user_data_ref) { 87836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator->ReleaseObjectReference(stack_[id].user_data_ref); 87936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe stack_[id].user_data_ref = 0; 88036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 88136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 88236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 883319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid ThreadActivityTracker::RecordExceptionActivity(const void* program_counter, 884319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const void* origin, 885319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski Activity::Type type, 886319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const ActivityData& data) { 887319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // A thread-checker creates a lock to check the thread-id which means 888319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // re-entry into this code if lock acquisitions are being tracked. 889319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK(thread_checker_.CalledOnValidThread()); 890319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 891319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Fill the reusable exception activity. 892319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski Activity::FillFrom(&header_->last_exception, program_counter, origin, type, 893319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski data); 894319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 895319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The data has changed meaning that some other thread trying to copy the 896319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // contents for reporting purposes could get bad data. 897319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->data_unchanged.store(0, std::memory_order_relaxed); 898319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 899319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 90036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ThreadActivityTracker::IsValid() const { 901319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (header_->owner.data_id.load(std::memory_order_acquire) == 0 || 902319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->owner.process_id == 0 || header_->thread_ref.as_id == 0 || 903319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->start_time == 0 || header_->start_ticks == 0 || 90436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->stack_slots != stack_slots_ || 90536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe header_->thread_name[sizeof(header_->thread_name) - 1] != '\0') { 90636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 90736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 90836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 90936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return valid_; 91036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 91136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 91236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool ThreadActivityTracker::CreateSnapshot(Snapshot* output_snapshot) const { 91336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(output_snapshot); 91436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 91536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // There is no "called on valid thread" check for this method as it can be 91636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // called from other threads or even other processes. It is also the reason 91736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // why atomic operations must be used in certain places above. 91836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 91936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // It's possible for the data to change while reading it in such a way that it 92036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // invalidates the read. Make several attempts but don't try forever. 92136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const int kMaxAttempts = 10; 92236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t depth; 92336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 92436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Stop here if the data isn't valid. 92536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!IsValid()) 92636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 92736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 92836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Allocate the maximum size for the stack so it doesn't have to be done 92936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // during the time-sensitive snapshot operation. It is shrunk once the 93036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // actual size is known. 93136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe output_snapshot->activity_stack.reserve(stack_slots_); 93236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 93336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe for (int attempt = 0; attempt < kMaxAttempts; ++attempt) { 934319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Remember the data IDs to ensure nothing is replaced during the snapshot 935319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // operation. Use "acquire" so that all the non-atomic fields of the 936319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // structure are valid (at least at the current moment in time). 937319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const uint32_t starting_id = 938319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->owner.data_id.load(std::memory_order_acquire); 939f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe const int64_t starting_create_stamp = header_->owner.create_stamp; 940319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const int64_t starting_process_id = header_->owner.process_id; 94136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const int64_t starting_thread_id = header_->thread_ref.as_id; 94236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 943319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Write a non-zero value to |data_unchanged| so it's possible to detect 94436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // at the end that nothing has changed since copying the data began. A 94536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // "cst" operation is required to ensure it occurs before everything else. 94636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Using "cst" memory ordering is relatively expensive but this is only 94736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // done during analysis so doesn't directly affect the worker threads. 948319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->data_unchanged.store(1, std::memory_order_seq_cst); 94936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 95036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Fetching the current depth also "acquires" the contents of the stack. 95136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe depth = header_->current_depth.load(std::memory_order_acquire); 95236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t count = std::min(depth, stack_slots_); 95336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe output_snapshot->activity_stack.resize(count); 95436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (count > 0) { 95536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Copy the existing contents. Memcpy is used for speed. 95636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memcpy(&output_snapshot->activity_stack[0], stack_, 95736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe count * sizeof(Activity)); 95836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 95936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 960319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Capture the last exception. 961319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski memcpy(&output_snapshot->last_exception, &header_->last_exception, 962319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski sizeof(Activity)); 963319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 964319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // TODO(bcwhite): Snapshot other things here. 965319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 96636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Retry if something changed during the copy. A "cst" operation ensures 96736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // it must happen after all the above operations. 968319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (!header_->data_unchanged.load(std::memory_order_seq_cst)) 96936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe continue; 97036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 97136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Stack copied. Record it's full depth. 97236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe output_snapshot->activity_stack_depth = depth; 97336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 974319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Get the general thread information. 97536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe output_snapshot->thread_name = 97636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::string(header_->thread_name, sizeof(header_->thread_name) - 1); 977f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe output_snapshot->create_stamp = header_->owner.create_stamp; 97836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe output_snapshot->thread_id = header_->thread_ref.as_id; 979319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski output_snapshot->process_id = header_->owner.process_id; 98036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 98136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // All characters of the thread-name buffer were copied so as to not break 98236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // if the trailing NUL were missing. Now limit the length if the actual 98336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // name is shorter. 98436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe output_snapshot->thread_name.resize( 98536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe strlen(output_snapshot->thread_name.c_str())); 98636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 987319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // If the data ID has changed then the tracker has exited and the memory 988319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // reused by a new one. Try again. 989319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (header_->owner.data_id.load(std::memory_order_seq_cst) != starting_id || 990f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe output_snapshot->create_stamp != starting_create_stamp || 991319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski output_snapshot->process_id != starting_process_id || 99236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe output_snapshot->thread_id != starting_thread_id) { 99336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe continue; 99436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 99536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 99636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Only successful if the data is still valid once everything is done since 99736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // it's possible for the thread to end somewhere in the middle and all its 99836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // values become garbage. 99936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!IsValid()) 100036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 100136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 100236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Change all the timestamps in the activities from "ticks" to "wall" time. 100336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const Time start_time = Time::FromInternalValue(header_->start_time); 100436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const int64_t start_ticks = header_->start_ticks; 100536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe for (Activity& activity : output_snapshot->activity_stack) { 100636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe activity.time_internal = 1007319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski WallTimeFromTickTime(start_ticks, activity.time_internal, start_time) 100836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe .ToInternalValue(); 100936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 1010319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski output_snapshot->last_exception.time_internal = 1011319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski WallTimeFromTickTime(start_ticks, 1012319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski output_snapshot->last_exception.time_internal, 1013319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski start_time) 1014319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski .ToInternalValue(); 101536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 101636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Success! 101736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return true; 101836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 101936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 102036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Too many attempts. 102136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 102236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 102336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1024319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskiconst void* ThreadActivityTracker::GetBaseAddress() { 1025319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return header_; 1026319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1027319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1028f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid ThreadActivityTracker::SetOwningProcessIdForTesting(int64_t pid, 1029319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t stamp) { 1030319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski header_->owner.SetOwningProcessIdForTesting(pid, stamp); 1031319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1032319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1033319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski// static 1034319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskibool ThreadActivityTracker::GetOwningProcessId(const void* memory, 1035f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t* out_id, 1036319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t* out_stamp) { 1037319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const Header* header = reinterpret_cast<const Header*>(memory); 1038319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return OwningProcess::GetOwningProcessId(&header->owner, out_id, out_stamp); 1039319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1040319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 104136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static 104236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t ThreadActivityTracker::SizeForStackDepth(int stack_depth) { 104336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return static_cast<size_t>(stack_depth) * sizeof(Activity) + sizeof(Header); 104436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 104536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1046319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskistd::unique_ptr<ActivityUserData> 1047319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiThreadActivityTracker::CreateUserDataForActivity( 1048319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski Activity* activity, 1049319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ActivityTrackerMemoryAllocator* allocator) { 1050319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DCHECK_EQ(0U, activity->user_data_ref); 1051319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1052319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski PersistentMemoryAllocator::Reference ref = allocator->GetObjectReference(); 1053319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski void* memory = allocator->GetAsArray<char>(ref, kUserDataSize); 1054319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (memory) { 1055319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski std::unique_ptr<ActivityUserData> user_data = 1056319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski MakeUnique<ActivityUserData>(memory, kUserDataSize); 1057319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski activity->user_data_ref = ref; 1058319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski activity->user_data_id = user_data->id(); 1059319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return user_data; 1060319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1061319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1062319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Return a dummy object that will still accept (but ignore) Set() calls. 1063319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return MakeUnique<ActivityUserData>(); 1064319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1065319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 106636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The instantiation of the GlobalActivityTracker object. 106736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// The object held here will obviously not be destructed at process exit 106836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// but that's best since PersistentMemoryAllocator objects (that underlie 106936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// GlobalActivityTracker objects) are explicitly forbidden from doing anything 107036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// essential at exit anyway due to the fact that they depend on data managed 107136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// elsewhere and which could be destructed first. An AtomicWord is used instead 107236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// of std::atomic because the latter can create global ctors and dtors. 107336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesubtle::AtomicWord GlobalActivityTracker::g_tracker_ = 0; 107436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 107536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::ModuleInfo() {} 107636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::ModuleInfo(ModuleInfo&& rhs) = default; 107736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::ModuleInfo(const ModuleInfo& rhs) = default; 107836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo::~ModuleInfo() {} 107936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 108036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=( 108136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ModuleInfo&& rhs) = default; 108236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfo& GlobalActivityTracker::ModuleInfo::operator=( 108336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const ModuleInfo& rhs) = default; 108436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 108536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfoRecord::ModuleInfoRecord() {} 108636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ModuleInfoRecord::~ModuleInfoRecord() {} 108736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 108836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool GlobalActivityTracker::ModuleInfoRecord::DecodeTo( 108936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe GlobalActivityTracker::ModuleInfo* info, 109036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t record_size) const { 109136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Get the current "changes" indicator, acquiring all the other values. 109236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t current_changes = changes.load(std::memory_order_acquire); 109336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 109436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Copy out the dynamic information. 109536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->is_loaded = loaded != 0; 109636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->address = static_cast<uintptr_t>(address); 109736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->load_time = load_time; 109836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 109936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Check to make sure no information changed while being read. A "seq-cst" 110036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // operation is expensive but is only done during analysis and it's the only 110136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // way to ensure this occurs after all the accesses above. If changes did 110236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // occur then return a "not loaded" result so that |size| and |address| 110336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // aren't expected to be accurate. 110436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if ((current_changes & kModuleInformationChanging) != 0 || 110536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe changes.load(std::memory_order_seq_cst) != current_changes) { 110636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->is_loaded = false; 110736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 110836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 110936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Copy out the static information. These never change so don't have to be 111036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // protected by the atomic |current_changes| operations. 111136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->size = static_cast<size_t>(size); 111236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->timestamp = timestamp; 111336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe info->age = age; 111436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memcpy(info->identifier, identifier, sizeof(info->identifier)); 111536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 111636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (offsetof(ModuleInfoRecord, pickle) + pickle_size > record_size) 111736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 111836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Pickle pickler(pickle, pickle_size); 111936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PickleIterator iter(pickler); 112036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return iter.ReadString(&info->file) && iter.ReadString(&info->debug_file); 112136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 112236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 112336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool GlobalActivityTracker::ModuleInfoRecord::EncodeFrom( 112436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const GlobalActivityTracker::ModuleInfo& info, 112536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t record_size) { 112636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Pickle pickler; 112736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe bool okay = 112836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe pickler.WriteString(info.file) && pickler.WriteString(info.debug_file); 112936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!okay) { 113036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe NOTREACHED(); 113136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 113236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 113336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (offsetof(ModuleInfoRecord, pickle) + pickler.size() > record_size) { 113436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe NOTREACHED(); 113536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 113636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 113736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 113836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // These fields never changes and are done before the record is made 113936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // iterable so no thread protection is necessary. 114036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size = info.size; 114136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe timestamp = info.timestamp; 114236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe age = info.age; 114336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memcpy(identifier, info.identifier, sizeof(identifier)); 114436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memcpy(pickle, pickler.data(), pickler.size()); 114536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe pickle_size = pickler.size(); 114636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe changes.store(0, std::memory_order_relaxed); 114736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1148319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Initialize the owner info. 1149319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski owner.Release_Initialize(); 1150319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 115136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Now set those fields that can change. 115236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return UpdateFrom(info); 115336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 115436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 115536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abebool GlobalActivityTracker::ModuleInfoRecord::UpdateFrom( 115636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const GlobalActivityTracker::ModuleInfo& info) { 115736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Updates can occur after the record is made visible so make changes atomic. 115836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // A "strong" exchange ensures no false failures. 115936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t old_changes = changes.load(std::memory_order_relaxed); 116036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t new_changes = old_changes | kModuleInformationChanging; 116136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if ((old_changes & kModuleInformationChanging) != 0 || 116236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe !changes.compare_exchange_strong(old_changes, new_changes, 116336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::memory_order_acquire, 116436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::memory_order_acquire)) { 116536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe NOTREACHED() << "Multiple sources are updating module information."; 116636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return false; 116736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 116836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 116936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe loaded = info.is_loaded ? 1 : 0; 117036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe address = info.address; 117136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe load_time = Time::Now().ToInternalValue(); 117236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 117336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe bool success = changes.compare_exchange_strong(new_changes, old_changes + 1, 117436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::memory_order_release, 117536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::memory_order_relaxed); 117636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(success); 117736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return true; 117836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 117936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 118036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static 118136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abesize_t GlobalActivityTracker::ModuleInfoRecord::EncodedSize( 118236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const GlobalActivityTracker::ModuleInfo& info) { 118336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PickleSizer sizer; 118436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe sizer.AddString(info.file); 118536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe sizer.AddString(info.debug_file); 118636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 118736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return offsetof(ModuleInfoRecord, pickle) + sizeof(Pickle::Header) + 118836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe sizer.payload_size(); 118936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 119036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 119136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ScopedThreadActivity::ScopedThreadActivity( 119236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 119336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* origin, 119436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::Type type, 119536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const ActivityData& data, 119636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe bool lock_allowed) 119736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : ThreadActivityTracker::ScopedActivity(GetOrCreateTracker(lock_allowed), 119836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe program_counter, 119936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe origin, 120036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe type, 120136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe data) {} 120236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 120336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ScopedThreadActivity::~ScopedThreadActivity() { 120436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (tracker_ && tracker_->HasUserData(activity_id_)) { 120536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe GlobalActivityTracker* global = GlobalActivityTracker::Get(); 120636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe AutoLock lock(global->user_data_allocator_lock_); 120736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe tracker_->ReleaseUserData(activity_id_, &global->user_data_allocator_); 120836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 120936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 121036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 121136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeActivityUserData& GlobalActivityTracker::ScopedThreadActivity::user_data() { 121236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!user_data_) { 121336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (tracker_) { 121436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe GlobalActivityTracker* global = GlobalActivityTracker::Get(); 121536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe AutoLock lock(global->user_data_allocator_lock_); 121636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe user_data_ = 121736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe tracker_->GetUserData(activity_id_, &global->user_data_allocator_); 121836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } else { 1219319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski user_data_ = MakeUnique<ActivityUserData>(); 122036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 122136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 122236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return *user_data_; 122336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 122436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1225319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiGlobalActivityTracker::ThreadSafeUserData::ThreadSafeUserData(void* memory, 1226f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe size_t size, 1227f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t pid) 1228f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe : ActivityUserData(memory, size, pid) {} 122936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1230319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub PawlowskiGlobalActivityTracker::ThreadSafeUserData::~ThreadSafeUserData() {} 123136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1232319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::ThreadSafeUserData::Set(StringPiece name, 1233319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ValueType type, 1234319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const void* memory, 1235319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski size_t size) { 123636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe AutoLock lock(data_lock_); 123736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityUserData::Set(name, type, memory, size); 123836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 123936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 124036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ManagedActivityTracker::ManagedActivityTracker( 124136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PersistentMemoryAllocator::Reference mem_reference, 124236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe void* base, 124336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t size) 124436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : ThreadActivityTracker(base, size), 124536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe mem_reference_(mem_reference), 124636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe mem_base_(base) {} 124736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 124836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::ManagedActivityTracker::~ManagedActivityTracker() { 124936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The global |g_tracker_| must point to the owner of this class since all 125036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // objects of this type must be destructed before |g_tracker_| can be changed 125136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // (something that only occurs in tests). 125236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(g_tracker_); 125336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe GlobalActivityTracker::Get()->ReturnTrackerMemory(this); 125436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 125536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 125636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::CreateWithAllocator( 125736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::unique_ptr<PersistentMemoryAllocator> allocator, 1258f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int stack_depth, 1259f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t process_id) { 126036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // There's no need to do anything with the result. It is self-managing. 126136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe GlobalActivityTracker* global_tracker = 1262f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe new GlobalActivityTracker(std::move(allocator), stack_depth, process_id); 126336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Create a tracker for this thread since it is known. 126436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe global_tracker->CreateTrackerForCurrentThread(); 126536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 126636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 126736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if !defined(OS_NACL) 126836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static 126936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::CreateWithFile(const FilePath& file_path, 127036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t size, 127136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint64_t id, 127236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe StringPiece name, 127336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe int stack_depth) { 127436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(!file_path.empty()); 127536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_GE(static_cast<uint64_t>(std::numeric_limits<int64_t>::max()), size); 127636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 127736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Create and map the file into memory and make it globally available. 127836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::unique_ptr<MemoryMappedFile> mapped_file(new MemoryMappedFile()); 127936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe bool success = 128036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe mapped_file->Initialize(File(file_path, 128136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe File::FLAG_CREATE_ALWAYS | File::FLAG_READ | 128236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe File::FLAG_WRITE | File::FLAG_SHARE_DELETE), 128336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe {0, static_cast<int64_t>(size)}, 128436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe MemoryMappedFile::READ_WRITE_EXTEND); 128536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(success); 128636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe CreateWithAllocator(MakeUnique<FilePersistentMemoryAllocator>( 128736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::move(mapped_file), size, id, name, false), 1288f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe stack_depth, 0); 128936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 129036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif // !defined(OS_NACL) 129136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 129236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static 129336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::CreateWithLocalMemory(size_t size, 129436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint64_t id, 129536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe StringPiece name, 1296f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int stack_depth, 1297f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t process_id) { 129836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe CreateWithAllocator( 1299f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe MakeUnique<LocalPersistentMemoryAllocator>(size, id, name), stack_depth, 1300f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe process_id); 1301f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe} 1302f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 1303f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// static 1304f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid GlobalActivityTracker::SetForTesting( 1305f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe std::unique_ptr<GlobalActivityTracker> tracker) { 1306f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe CHECK(!subtle::NoBarrier_Load(&g_tracker_)); 1307f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe subtle::Release_Store(&g_tracker_, 1308f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe reinterpret_cast<uintptr_t>(tracker.release())); 130936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 131036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1311f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe// static 1312f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abestd::unique_ptr<GlobalActivityTracker> 1313f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko AbeGlobalActivityTracker::ReleaseForTesting() { 1314f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe GlobalActivityTracker* tracker = Get(); 1315f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe if (!tracker) 1316f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe return nullptr; 1317f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 1318f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // Thread trackers assume that the global tracker is present for some 1319f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe // operations so ensure that there aren't any. 1320f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe tracker->ReleaseTrackerForCurrentThreadForTesting(); 1321f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK_EQ(0, tracker->thread_tracker_count_.load(std::memory_order_relaxed)); 1322f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 1323f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe subtle::Release_Store(&g_tracker_, 0); 1324f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe return WrapUnique(tracker); 1325f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe}; 1326f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe 132736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeThreadActivityTracker* GlobalActivityTracker::CreateTrackerForCurrentThread() { 132836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(!this_thread_tracker_.Get()); 132936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 133036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PersistentMemoryAllocator::Reference mem_reference; 133136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 133236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe { 133336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe base::AutoLock autolock(thread_tracker_allocator_lock_); 133436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe mem_reference = thread_tracker_allocator_.GetObjectReference(); 133536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 133636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 133736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!mem_reference) { 133836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Failure. This shouldn't happen. But be graceful if it does, probably 133936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // because the underlying allocator wasn't given enough memory to satisfy 134036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // to all possible requests. 134136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe NOTREACHED(); 134236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Report the thread-count at which the allocator was full so that the 134336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // failure can be seen and underlying memory resized appropriately. 134436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe UMA_HISTOGRAM_COUNTS_1000( 134536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe "ActivityTracker.ThreadTrackers.MemLimitTrackerCount", 134636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_tracker_count_.load(std::memory_order_relaxed)); 134736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Return null, just as if tracking wasn't enabled. 134836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return nullptr; 134936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 135036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 135136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Convert the memory block found above into an actual memory address. 135236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Doing the conversion as a Header object enacts the 32/64-bit size 135336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // consistency checks which would not otherwise be done. Unfortunately, 135436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // some older compilers and MSVC don't have standard-conforming definitions 135536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // of std::atomic which cause it not to be plain-old-data. Don't check on 135636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // those platforms assuming that the checks on other platforms will be 135736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // sufficient. 135836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // TODO(bcwhite): Review this after major compiler releases. 135936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(mem_reference); 136036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe void* mem_base; 136136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe mem_base = 136236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->GetAsObject<ThreadActivityTracker::Header>(mem_reference); 136336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 136436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(mem_base); 136536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_LE(stack_memory_size_, allocator_->GetAllocSize(mem_reference)); 136636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 136736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Create a tracker with the acquired memory and set it as the tracker 136836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // for this particular thread in thread-local-storage. 136936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ManagedActivityTracker* tracker = 137036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe new ManagedActivityTracker(mem_reference, mem_base, stack_memory_size_); 137136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(tracker->IsValid()); 137236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe this_thread_tracker_.Set(tracker); 137336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe int old_count = thread_tracker_count_.fetch_add(1, std::memory_order_relaxed); 137436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 137536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe UMA_HISTOGRAM_ENUMERATION("ActivityTracker.ThreadTrackers.Count", 137636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe old_count + 1, kMaxThreadCount); 137736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return tracker; 137836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 137936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 138036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::ReleaseTrackerForCurrentThreadForTesting() { 138136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ThreadActivityTracker* tracker = 138236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe reinterpret_cast<ThreadActivityTracker*>(this_thread_tracker_.Get()); 1383f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe if (tracker) { 1384f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe this_thread_tracker_.Set(nullptr); 138536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe delete tracker; 1386f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe } 138736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 138836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1389319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::SetBackgroundTaskRunner( 1390319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const scoped_refptr<TaskRunner>& runner) { 1391319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski AutoLock lock(global_tracker_lock_); 1392319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski background_task_runner_ = runner; 1393319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1394319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1395319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::SetProcessExitCallback( 1396319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ProcessExitCallback callback) { 1397319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski AutoLock lock(global_tracker_lock_); 1398319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_exit_callback_ = callback; 1399319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1400319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1401319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordProcessLaunch( 1402319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ProcessId process_id, 1403319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const FilePath::StringType& cmd) { 1404f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe const int64_t pid = process_id; 1405f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK_NE(GetProcessId(), pid); 1406f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK_NE(0, pid); 1407319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1408319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski base::AutoLock lock(global_tracker_lock_); 1409f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe if (base::ContainsKey(known_processes_, pid)) { 1410319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // TODO(bcwhite): Measure this in UMA. 1411319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski NOTREACHED() << "Process #" << process_id 1412319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski << " was previously recorded as \"launched\"" 1413319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski << " with no corresponding exit."; 1414f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe known_processes_.erase(pid); 1415319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1416319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1417319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#if defined(OS_WIN) 1418f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe known_processes_.insert(std::make_pair(pid, UTF16ToUTF8(cmd))); 1419319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#else 1420f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe known_processes_.insert(std::make_pair(pid, cmd)); 1421319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski#endif 1422319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1423319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1424319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordProcessLaunch( 1425319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ProcessId process_id, 1426319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const FilePath::StringType& exe, 1427319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const FilePath::StringType& args) { 1428f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe const int64_t pid = process_id; 1429319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (exe.find(FILE_PATH_LITERAL(" "))) { 1430f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe RecordProcessLaunch(pid, FilePath::StringType(FILE_PATH_LITERAL("\"")) + 1431f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe exe + FILE_PATH_LITERAL("\" ") + args); 1432319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } else { 1433f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe RecordProcessLaunch(pid, exe + FILE_PATH_LITERAL(' ') + args); 1434319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1435319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1436319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1437319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordProcessExit(ProcessId process_id, 1438319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int exit_code) { 1439f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe const int64_t pid = process_id; 1440f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK_NE(GetProcessId(), pid); 1441f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK_NE(0, pid); 1442319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1443319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski scoped_refptr<TaskRunner> task_runner; 1444319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski std::string command_line; 1445319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski { 1446319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski base::AutoLock lock(global_tracker_lock_); 1447319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski task_runner = background_task_runner_; 1448f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe auto found = known_processes_.find(pid); 1449319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (found != known_processes_.end()) { 1450319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski command_line = std::move(found->second); 1451319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski known_processes_.erase(found); 1452319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } else { 1453319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski DLOG(ERROR) << "Recording exit of unknown process #" << process_id; 1454319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1455319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1456319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1457319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Use the current time to differentiate the process that just exited 1458319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // from any that might be created in the future with the same ID. 1459319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t now_stamp = Time::Now().ToInternalValue(); 1460319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1461319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The persistent allocator is thread-safe so run the iteration and 1462319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // adjustments on a worker thread if one was provided. 1463319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (task_runner && !task_runner->RunsTasksOnCurrentThread()) { 1464319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski task_runner->PostTask( 1465319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski FROM_HERE, 1466f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe Bind(&GlobalActivityTracker::CleanupAfterProcess, Unretained(this), pid, 1467f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe now_stamp, exit_code, Passed(&command_line))); 1468319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return; 1469319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1470319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1471f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe CleanupAfterProcess(pid, now_stamp, exit_code, std::move(command_line)); 1472319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1473319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1474319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::SetProcessPhase(ProcessPhase phase) { 1475319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_data().SetInt(kProcessPhaseDataKey, phase); 1476319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1477319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1478f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abevoid GlobalActivityTracker::CleanupAfterProcess(int64_t process_id, 1479319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t exit_stamp, 1480319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int exit_code, 1481319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski std::string&& command_line) { 1482319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The process may not have exited cleanly so its necessary to go through 1483319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // all the data structures it may have allocated in the persistent memory 1484319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // segment and mark them as "released". This will allow them to be reused 1485319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // later on. 1486319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1487319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski PersistentMemoryAllocator::Iterator iter(allocator_.get()); 1488319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski PersistentMemoryAllocator::Reference ref; 1489319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1490319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ProcessExitCallback process_exit_callback; 1491319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski { 1492319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski AutoLock lock(global_tracker_lock_); 1493319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_exit_callback = process_exit_callback_; 1494319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1495319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (process_exit_callback) { 1496319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Find the processes user-data record so the process phase can be passed 1497319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // to the callback. 1498319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ActivityUserData::Snapshot process_data_snapshot; 1499319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski while ((ref = iter.GetNextOfType(kTypeIdProcessDataRecord)) != 0) { 1500319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const void* memory = allocator_->GetAsArray<char>( 1501319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ref, kTypeIdProcessDataRecord, PersistentMemoryAllocator::kSizeAny); 1502f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t found_id; 1503319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t create_stamp; 1504319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (ActivityUserData::GetOwningProcessId(memory, &found_id, 1505319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski &create_stamp)) { 1506319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (found_id == process_id && create_stamp < exit_stamp) { 1507319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const ActivityUserData process_data(const_cast<void*>(memory), 1508319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski allocator_->GetAllocSize(ref)); 1509319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_data.CreateSnapshot(&process_data_snapshot); 1510319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski break; // No need to look for any others. 1511319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1512319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1513319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1514319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski iter.Reset(); // So it starts anew when used below. 1515319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1516319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Record the process's phase at exit so callback doesn't need to go 1517319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // searching based on a private key value. 1518319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ProcessPhase exit_phase = PROCESS_PHASE_UNKNOWN; 1519319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski auto phase = process_data_snapshot.find(kProcessPhaseDataKey); 1520319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (phase != process_data_snapshot.end()) 1521319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski exit_phase = static_cast<ProcessPhase>(phase->second.GetInt()); 1522319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1523319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Perform the callback. 1524319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_exit_callback.Run(process_id, exit_stamp, exit_code, exit_phase, 1525319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski std::move(command_line), 1526319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski std::move(process_data_snapshot)); 1527319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1528319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1529319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Find all allocations associated with the exited process and free them. 1530319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t type; 1531319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski while ((ref = iter.GetNext(&type)) != 0) { 1532319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski switch (type) { 1533319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case kTypeIdActivityTracker: 1534319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case kTypeIdUserDataRecord: 1535319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case kTypeIdProcessDataRecord: 1536319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski case ModuleInfoRecord::kPersistentTypeId: { 1537319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const void* memory = allocator_->GetAsArray<char>( 1538319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ref, type, PersistentMemoryAllocator::kSizeAny); 1539f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t found_id; 1540319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski int64_t create_stamp; 1541319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1542319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // By convention, the OwningProcess structure is always the first 1543319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // field of the structure so there's no need to handle all the 1544319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // cases separately. 1545319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (OwningProcess::GetOwningProcessId(memory, &found_id, 1546319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski &create_stamp)) { 1547319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Only change the type to be "free" if the process ID matches and 1548319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // the creation time is before the exit time (so PID re-use doesn't 1549319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // cause the erasure of something that is in-use). Memory is cleared 1550319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // here, rather than when it's needed, so as to limit the impact at 1551319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // that critical time. 1552319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (found_id == process_id && create_stamp < exit_stamp) 1553319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski allocator_->ChangeType(ref, ~type, type, /*clear=*/true); 1554319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1555319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } break; 1556319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1557319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski } 1558319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1559319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 156036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::RecordLogMessage(StringPiece message) { 156136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Allocate at least one extra byte so the string is NUL terminated. All 156236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // memory returned by the allocator is guaranteed to be zeroed. 156336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PersistentMemoryAllocator::Reference ref = 156436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->Allocate(message.size() + 1, kTypeIdGlobalLogMessage); 156536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe char* memory = allocator_->GetAsArray<char>(ref, kTypeIdGlobalLogMessage, 156636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe message.size() + 1); 156736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (memory) { 156836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe memcpy(memory, message.data(), message.size()); 156936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->MakeIterable(ref); 157036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 157136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 157236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 157336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::RecordModuleInfo(const ModuleInfo& info) { 157436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe AutoLock lock(modules_lock_); 157536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe auto found = modules_.find(info.file); 157636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (found != modules_.end()) { 157736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ModuleInfoRecord* record = found->second; 157836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(record); 157936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 158036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Update the basic state of module information that has been already 158136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // recorded. It is assumed that the string information (identifier, 158236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // version, etc.) remain unchanged which means that there's no need 158336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // to create a new record to accommodate a possibly longer length. 158436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe record->UpdateFrom(info); 158536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 158636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe } 158736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 158836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe size_t required_size = ModuleInfoRecord::EncodedSize(info); 158936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ModuleInfoRecord* record = allocator_->New<ModuleInfoRecord>(required_size); 159036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe if (!record) 159136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe return; 159236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 159336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe bool success = record->EncodeFrom(info, required_size); 159436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(success); 159536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->MakeIterable(record); 159636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe modules_.insert(std::make_pair(info.file, record)); 159736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 159836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 159936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::RecordFieldTrial(const std::string& trial_name, 160036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe StringPiece group_name) { 160136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const std::string key = std::string("FieldTrial.") + trial_name; 160236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe global_data_.SetString(key, group_name); 160336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 160436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 160536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::GlobalActivityTracker( 160636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe std::unique_ptr<PersistentMemoryAllocator> allocator, 1607f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int stack_depth, 1608f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe int64_t process_id) 160936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : allocator_(std::move(allocator)), 161036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe stack_memory_size_(ThreadActivityTracker::SizeForStackDepth(stack_depth)), 1611f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe process_id_(process_id == 0 ? GetCurrentProcId() : process_id), 161236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe this_thread_tracker_(&OnTLSDestroy), 161336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_tracker_count_(0), 161436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_tracker_allocator_(allocator_.get(), 161536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kTypeIdActivityTracker, 161636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kTypeIdActivityTrackerFree, 161736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe stack_memory_size_, 161836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kCachedThreadMemories, 161936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*make_iterable=*/true), 162036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe user_data_allocator_(allocator_.get(), 162136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kTypeIdUserDataRecord, 162236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kTypeIdUserDataRecordFree, 162336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kUserDataSize, 162436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kCachedUserDataMemories, 1625319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski /*make_iterable=*/true), 1626319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_data_(allocator_->GetAsArray<char>( 1627319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski AllocateFrom(allocator_.get(), 1628319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski kTypeIdProcessDataRecordFree, 1629319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski kProcessDataSize, 1630319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski kTypeIdProcessDataRecord), 1631319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski kTypeIdProcessDataRecord, 1632319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski kProcessDataSize), 1633f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe kProcessDataSize, 1634f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe process_id_), 163536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe global_data_( 163636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->GetAsArray<char>( 163736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->Allocate(kGlobalDataSize, kTypeIdGlobalDataRecord), 163836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kTypeIdGlobalDataRecord, 1639319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski kGlobalDataSize), 1640f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe kGlobalDataSize, 1641f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe process_id_) { 1642f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK_NE(0, process_id_); 164336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 164436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Ensure that there is no other global object and then make this one such. 164536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(!g_tracker_); 164636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe subtle::Release_Store(&g_tracker_, reinterpret_cast<uintptr_t>(this)); 164736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1648319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // The data records must be iterable in order to be found by an analyzer. 1649319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski allocator_->MakeIterable(allocator_->GetAsReference( 1650319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski process_data_.GetBaseAddress(), kTypeIdProcessDataRecord)); 165136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe allocator_->MakeIterable(allocator_->GetAsReference( 165236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe global_data_.GetBaseAddress(), kTypeIdGlobalDataRecord)); 165336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1654319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Note that this process has launched. 1655319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski SetProcessPhase(PROCESS_LAUNCHED); 1656319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 165736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Fetch and record all activated field trials. 165836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe FieldTrial::ActiveGroups active_groups; 165936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe FieldTrialList::GetActiveFieldTrialGroups(&active_groups); 166036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe for (auto& group : active_groups) 166136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe RecordFieldTrial(group.trial_name, group.group_name); 166236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 166336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 166436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeGlobalActivityTracker::~GlobalActivityTracker() { 1665f810b5921dde57180956b9eadf39a3a2b8cb5855Hidehiko Abe DCHECK(Get() == nullptr || Get() == this); 166636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, thread_tracker_count_.load(std::memory_order_relaxed)); 166736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe subtle::Release_Store(&g_tracker_, 0); 166836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 166936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 167036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::ReturnTrackerMemory( 167136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ManagedActivityTracker* tracker) { 167236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe PersistentMemoryAllocator::Reference mem_reference = tracker->mem_reference_; 167336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe void* mem_base = tracker->mem_base_; 167436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(mem_reference); 167536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK(mem_base); 167636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 167736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Remove the destructed tracker from the set of known ones. 167836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_LE(1, thread_tracker_count_.load(std::memory_order_relaxed)); 167936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_tracker_count_.fetch_sub(1, std::memory_order_relaxed); 168036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 168136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // Release this memory for re-use at a later time. 168236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe base::AutoLock autolock(thread_tracker_allocator_lock_); 168336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe thread_tracker_allocator_.ReleaseObjectReference(mem_reference); 168436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 168536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 1686319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowskivoid GlobalActivityTracker::RecordExceptionImpl(const void* pc, 1687319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski const void* origin, 1688319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski uint32_t code) { 1689319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // Get an existing tracker for this thread. It's not possible to create 1690319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // one at this point because such would involve memory allocations and 1691319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // other potentially complex operations that can cause failures if done 1692319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // within an exception handler. In most cases various operations will 1693319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // have already created the tracker so this shouldn't generally be a 1694319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski // problem. 1695319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ThreadActivityTracker* tracker = GetTrackerForCurrentThread(); 1696319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski if (!tracker) 1697319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski return; 1698319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 1699319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski tracker->RecordExceptionActivity(pc, origin, Activity::ACT_EXCEPTION, 1700319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski ActivityData::ForException(code)); 1701319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski} 1702319afc59a539d6261307aadbdab4d4ee93eaf1ffJakub Pawlowski 170336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe// static 170436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid GlobalActivityTracker::OnTLSDestroy(void* value) { 170536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe delete reinterpret_cast<ManagedActivityTracker*>(value); 170636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 170736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 170836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedActivity::ScopedActivity(const void* program_counter, 170936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint8_t action, 171036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe uint32_t id, 171136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe int32_t info) 171236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : GlobalActivityTracker::ScopedThreadActivity( 171336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe program_counter, 171436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe nullptr, 171536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe static_cast<Activity::Type>(Activity::ACT_GENERIC | action), 171636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityData::ForGeneric(id, info), 171736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*lock_allowed=*/true), 171836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe id_(id) { 171936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe // The action must not affect the category bits of the activity type. 172036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); 172136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 172236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 172336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ScopedActivity::ChangeAction(uint8_t action) { 172436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); 172536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action), 172636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe kNullActivityData); 172736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 172836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 172936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ScopedActivity::ChangeInfo(int32_t info) { 173036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ChangeTypeAndData(Activity::ACT_NULL, ActivityData::ForGeneric(id_, info)); 173136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 173236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 173336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abevoid ScopedActivity::ChangeActionAndInfo(uint8_t action, int32_t info) { 173436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe DCHECK_EQ(0, action & Activity::ACT_CATEGORY_MASK); 173536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ChangeTypeAndData(static_cast<Activity::Type>(Activity::ACT_GENERIC | action), 173636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityData::ForGeneric(id_, info)); 173736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} 173836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 173936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedTaskRunActivity::ScopedTaskRunActivity( 174036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 174136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const base::PendingTask& task) 174236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : GlobalActivityTracker::ScopedThreadActivity( 174336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe program_counter, 174436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe task.posted_from.program_counter(), 174536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::ACT_TASK_RUN, 174636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityData::ForTask(task.sequence_num), 174736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*lock_allowed=*/true) {} 174836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 174936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedLockAcquireActivity::ScopedLockAcquireActivity( 175036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 175136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const base::internal::LockImpl* lock) 175236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : GlobalActivityTracker::ScopedThreadActivity( 175336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe program_counter, 175436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe nullptr, 175536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::ACT_LOCK_ACQUIRE, 175636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityData::ForLock(lock), 175736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*lock_allowed=*/false) {} 175836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 175936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedEventWaitActivity::ScopedEventWaitActivity( 176036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 176136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const base::WaitableEvent* event) 176236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : GlobalActivityTracker::ScopedThreadActivity( 176336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe program_counter, 176436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe nullptr, 176536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::ACT_EVENT_WAIT, 176636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityData::ForEvent(event), 176736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*lock_allowed=*/true) {} 176836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 176936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedThreadJoinActivity::ScopedThreadJoinActivity( 177036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 177136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const base::PlatformThreadHandle* thread) 177236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : GlobalActivityTracker::ScopedThreadActivity( 177336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe program_counter, 177436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe nullptr, 177536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::ACT_THREAD_JOIN, 177636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityData::ForThread(*thread), 177736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*lock_allowed=*/true) {} 177836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 177936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#if !defined(OS_NACL) && !defined(OS_IOS) 178036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko AbeScopedProcessWaitActivity::ScopedProcessWaitActivity( 178136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const void* program_counter, 178236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe const base::Process* process) 178336040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe : GlobalActivityTracker::ScopedThreadActivity( 178436040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe program_counter, 178536040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe nullptr, 178636040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe Activity::ACT_PROCESS_WAIT, 178736040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe ActivityData::ForProcess(process->Pid()), 178836040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe /*lock_allowed=*/true) {} 178936040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe#endif 179036040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe 179136040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} // namespace debug 179236040ed30c39d2106a2cd5ec033e98b71302a744Hidehiko Abe} // namespace base 1793