17bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris/* 27bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * Copyright (C) 2016 The Android Open Source Project 37bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * All rights reserved. 47bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * 57bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * Redistribution and use in source and binary forms, with or without 67bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * modification, are permitted provided that the following conditions 77bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * are met: 87bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * * Redistributions of source code must retain the above copyright 97bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * notice, this list of conditions and the following disclaimer. 107bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * * Redistributions in binary form must reproduce the above copyright 117bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * notice, this list of conditions and the following disclaimer in 127bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * the documentation and/or other materials provided with the 137bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * distribution. 147bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * 157bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 167bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 177bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 187bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 197bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 207bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 217bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 227bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 237bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 247bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 257bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 267bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris * SUCH DAMAGE. 277bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris */ 287bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 297bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <errno.h> 307bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <fcntl.h> 317bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <pthread.h> 327bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <stdatomic.h> 337bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <stdint.h> 347bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <stdio.h> 357bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <stdlib.h> 367bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <sys/types.h> 377bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 387bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <mutex> 397bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 407bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include <android-base/stringprintf.h> 417bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 427bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include "Config.h" 437bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include "DebugData.h" 447bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include "RecordData.h" 458b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "debug_disable.h" 468b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris#include "debug_log.h" 477bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 487bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisRecordEntry::RecordEntry() : tid_(gettid()) { 497bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 507bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 517bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string ThreadCompleteEntry::GetString() const { 527bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris return android::base::StringPrintf("%d: thread_done 0x0\n", tid_); 537bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 547bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 558b70a0266d42297e9b38e6209588eb3621843e95Christopher FerrisAllocEntry::AllocEntry(void* pointer) : pointer_(pointer) {} 567bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 578b70a0266d42297e9b38e6209588eb3621843e95Christopher FerrisMallocEntry::MallocEntry(void* pointer, size_t size) : AllocEntry(pointer), size_(size) {} 587bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 597bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string MallocEntry::GetString() const { 607bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris return android::base::StringPrintf("%d: malloc %p %zu\n", tid_, pointer_, size_); 617bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 627bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 638b70a0266d42297e9b38e6209588eb3621843e95Christopher FerrisFreeEntry::FreeEntry(void* pointer) : AllocEntry(pointer) {} 647bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 657bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string FreeEntry::GetString() const { 667bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris return android::base::StringPrintf("%d: free %p\n", tid_, pointer_); 677bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 687bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 697bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisCallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size) 708b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris : MallocEntry(pointer, size), nmemb_(nmemb) {} 717bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 727bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string CallocEntry::GetString() const { 737bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris return android::base::StringPrintf("%d: calloc %p %zu %zu\n", tid_, pointer_, nmemb_, size_); 747bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 757bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 767bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer) 778b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris : MallocEntry(pointer, size), old_pointer_(old_pointer) {} 787bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 797bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string ReallocEntry::GetString() const { 808b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return android::base::StringPrintf("%d: realloc %p %p %zu\n", tid_, pointer_, old_pointer_, size_); 817bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 827bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 83d69ee59594088c0d92ba9273188ef53ea5e6cd6aChristopher Ferris// aligned_alloc, posix_memalign, memalign, pvalloc, valloc all recorded with this class. 847bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisMemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment) 858b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris : MallocEntry(pointer, size), alignment_(alignment) {} 867bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 877bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string MemalignEntry::GetString() const { 888b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris return android::base::StringPrintf("%d: memalign %p %zu %zu\n", tid_, pointer_, alignment_, size_); 897bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 907bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 917bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstruct ThreadData { 928b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris ThreadData(RecordData* record_data, ThreadCompleteEntry* entry) 938b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris : record_data(record_data), entry(entry) {} 947bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris RecordData* record_data; 957bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris ThreadCompleteEntry* entry; 967bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris size_t count = 0; 977bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}; 987bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 997bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstatic void ThreadKeyDelete(void* data) { 1007bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris ThreadData* thread_data = reinterpret_cast<ThreadData*>(data); 1017bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1027bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris thread_data->count++; 1037bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1047bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // This should be the last time we are called. 1057bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (thread_data->count == 4) { 1067bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris ScopedDisableDebugCalls disable; 1077bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1087bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris thread_data->record_data->AddEntryOnly(thread_data->entry); 1097bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris delete thread_data; 1107bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } else { 1117bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris pthread_setspecific(thread_data->record_data->key(), data); 1127bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1137bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 1147bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1157bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstatic void RecordDump(int, siginfo_t*, void*) { 1167bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // It's not necessarily safe to do the dump here, instead wait for the 1177bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // next allocation call to do the dump. 1187bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris g_debug->record->SetToDump(); 1197bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 1207bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1217bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisvoid RecordData::Dump() { 1227bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris std::lock_guard<std::mutex> lock(dump_lock_); 1237bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1247bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // Make it so that no more entries can be added while dumping. 1257bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris unsigned int last_entry_index = cur_index_.exchange(static_cast<unsigned int>(num_entries_)); 1267bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (dump_ == false) { 1277bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // Multiple Dump() calls from different threads, and we lost. Do nothing. 1287bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris return; 1297bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1307bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1317bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // cur_index_ keeps getting incremented even if we hit the num_entries_. 1327bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // If that happens, cap the entries to dump by num_entries_. 1337bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (last_entry_index > num_entries_) { 1347bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris last_entry_index = num_entries_; 1357bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1367bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1378b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris int dump_fd = 1388b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris open(dump_file_.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW, 0755); 1397bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (dump_fd != -1) { 1407bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris for (size_t i = 0; i < last_entry_index; i++) { 1417bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris std::string line = entries_[i]->GetString(); 1427bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris ssize_t bytes = write(dump_fd, line.c_str(), line.length()); 1437bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (bytes == -1 || static_cast<size_t>(bytes) != line.length()) { 1447bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris error_log("Failed to write record alloc information: %s", strerror(errno)); 1457bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // Free all of the rest of the errors, we don't have any way 1467bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // to dump a partial list of the entries. 1477bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris for (i++; i < last_entry_index; i++) { 1487bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris delete entries_[i]; 1497bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris entries_[i] = nullptr; 1507bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1517bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris break; 1527bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1537bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris delete entries_[i]; 1547bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris entries_[i] = nullptr; 1557bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1567bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris close(dump_fd); 1577bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1587bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // Mark the entries dumped. 1597bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris cur_index_ = 0U; 1607bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } else { 1617bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris error_log("Cannot create record alloc file %s: %s", dump_file_.c_str(), strerror(errno)); 1627bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // Since we couldn't create the file, reset the entries dumped back 1637bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // to the original value. 1647bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris cur_index_ = last_entry_index; 1657bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1667bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1677bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris dump_ = false; 1687bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 1697bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1707bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisRecordData::RecordData() { 1717bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris pthread_key_create(&key_, ThreadKeyDelete); 1727bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 1737bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1747bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisbool RecordData::Initialize(const Config& config) { 1753e235911c9cf5062adbb73efb53fe5ed712d7c53Elliott Hughes struct sigaction64 dump_act = {}; 1767bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris dump_act.sa_sigaction = RecordDump; 1777bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris dump_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; 1783e235911c9cf5062adbb73efb53fe5ed712d7c53Elliott Hughes if (sigaction64(config.record_allocs_signal(), &dump_act, nullptr) != 0) { 1797bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris error_log("Unable to set up record dump signal function: %s", strerror(errno)); 1807bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris return false; 1817bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 1827bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris pthread_setspecific(key_, nullptr); 1837bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1847bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris info_log("%s: Run: 'kill -%d %d' to dump the allocation records.", getprogname(), 1852b2b25b87827102671cdd4b25c01aa22a9971a63Christopher Ferris config.record_allocs_signal(), getpid()); 1867bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1872b2b25b87827102671cdd4b25c01aa22a9971a63Christopher Ferris num_entries_ = config.record_allocs_num_entries(); 1887bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris entries_ = new const RecordEntry*[num_entries_]; 1897bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris cur_index_ = 0; 1907bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris dump_ = false; 1912b2b25b87827102671cdd4b25c01aa22a9971a63Christopher Ferris dump_file_ = config.record_allocs_file(); 1927bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1937bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris return true; 1947bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 1957bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 1967bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisRecordData::~RecordData() { 1978b70a0266d42297e9b38e6209588eb3621843e95Christopher Ferris delete[] entries_; 1987bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris pthread_key_delete(key_); 1997bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 2007bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 2017bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisvoid RecordData::AddEntryOnly(const RecordEntry* entry) { 2027bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris unsigned int entry_index = cur_index_.fetch_add(1); 2037bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (entry_index < num_entries_) { 2047bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris entries_[entry_index] = entry; 2057bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 2067bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 2077bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 2087bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisvoid RecordData::AddEntry(const RecordEntry* entry) { 2097bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris void* data = pthread_getspecific(key_); 2107bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (data == nullptr) { 2117bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris ThreadData* thread_data = new ThreadData(this, new ThreadCompleteEntry()); 2127bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris pthread_setspecific(key_, thread_data); 2137bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 2147bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 2157bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris AddEntryOnly(entry); 2167bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris 2177bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris // Check to see if it's time to dump the entries. 2187bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris if (dump_) { 2197bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris Dump(); 2207bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris } 2217bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris} 222