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