RecordData.cpp revision 2b2b25b87827102671cdd4b25c01aa22a9971a63
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 "debug_disable.h"
447bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include "debug_log.h"
457bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include "DebugData.h"
467bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris#include "RecordData.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
557bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisAllocEntry::AllocEntry(void* pointer) : pointer_(pointer) {
567bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
577bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
587bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisMallocEntry::MallocEntry(void* pointer, size_t size) : AllocEntry(pointer), size_(size) {
597bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
607bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
617bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string MallocEntry::GetString() const {
627bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  return android::base::StringPrintf("%d: malloc %p %zu\n", tid_, pointer_, size_);
637bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
647bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
657bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisFreeEntry::FreeEntry(void* pointer) : AllocEntry(pointer) {
667bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
677bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
687bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string FreeEntry::GetString() const {
697bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  return android::base::StringPrintf("%d: free %p\n", tid_, pointer_);
707bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
717bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
727bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisCallocEntry::CallocEntry(void* pointer, size_t nmemb, size_t size)
737bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    : MallocEntry(pointer, size), nmemb_(nmemb) {
747bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
757bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
767bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string CallocEntry::GetString() const {
777bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  return android::base::StringPrintf("%d: calloc %p %zu %zu\n", tid_, pointer_, nmemb_, size_);
787bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
797bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
807bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisReallocEntry::ReallocEntry(void* pointer, size_t size, void* old_pointer)
817bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    : MallocEntry(pointer, size), old_pointer_(old_pointer) {
827bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
837bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
847bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string ReallocEntry::GetString() const {
857bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  return android::base::StringPrintf("%d: realloc %p %p %zu\n", tid_, pointer_,
867bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris                                     old_pointer_, size_);
877bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
887bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
897bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris// posix_memalign, memalgin, pvalloc, valloc all recorded with this class.
907bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisMemalignEntry::MemalignEntry(void* pointer, size_t size, size_t alignment)
917bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    : MallocEntry(pointer, size), alignment_(alignment) {
927bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
937bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
947bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstd::string MemalignEntry::GetString() const {
957bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  return android::base::StringPrintf("%d: memalign %p %zu %zu\n", tid_, pointer_,
967bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris                                     alignment_, size_);
977bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
987bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
997bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstruct ThreadData {
1007bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  ThreadData(RecordData* record_data, ThreadCompleteEntry* entry) : record_data(record_data), entry(entry) {}
1017bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  RecordData* record_data;
1027bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  ThreadCompleteEntry* entry;
1037bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  size_t count = 0;
1047bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris};
1057bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1067bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstatic void ThreadKeyDelete(void* data) {
1077bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  ThreadData* thread_data = reinterpret_cast<ThreadData*>(data);
1087bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1097bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  thread_data->count++;
1107bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1117bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  // This should be the last time we are called.
1127bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  if (thread_data->count == 4) {
1137bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    ScopedDisableDebugCalls disable;
1147bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1157bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    thread_data->record_data->AddEntryOnly(thread_data->entry);
1167bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    delete thread_data;
1177bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  } else {
1187bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    pthread_setspecific(thread_data->record_data->key(), data);
1197bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
1207bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
1217bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1227bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisstatic void RecordDump(int, siginfo_t*, void*) {
1237bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  // It's not necessarily safe to do the dump here, instead wait for the
1247bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  // next allocation call to do the dump.
1257bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  g_debug->record->SetToDump();
1267bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
1277bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1287bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisvoid RecordData::Dump() {
1297bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  std::lock_guard<std::mutex> lock(dump_lock_);
1307bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1317bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  // Make it so that no more entries can be added while dumping.
1327bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  unsigned int last_entry_index = cur_index_.exchange(static_cast<unsigned int>(num_entries_));
1337bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  if (dump_ == false) {
1347bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    // Multiple Dump() calls from different threads, and we lost. Do nothing.
1357bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    return;
1367bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
1377bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1387bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  // cur_index_ keeps getting incremented even if we hit the num_entries_.
1397bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  // If that happens, cap the entries to dump by num_entries_.
1407bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  if (last_entry_index > num_entries_) {
1417bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    last_entry_index = num_entries_;
1427bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
1437bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1447bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  int dump_fd = open(dump_file_.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC | O_NOFOLLOW,
1457bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris                     0755);
1467bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  if (dump_fd != -1) {
1477bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    for (size_t i = 0; i < last_entry_index; i++) {
1487bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris      std::string line = entries_[i]->GetString();
1497bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris      ssize_t bytes = write(dump_fd, line.c_str(), line.length());
1507bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris      if (bytes == -1 || static_cast<size_t>(bytes) != line.length()) {
1517bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris        error_log("Failed to write record alloc information: %s", strerror(errno));
1527bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris        // Free all of the rest of the errors, we don't have any way
1537bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris        // to dump a partial list of the entries.
1547bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris        for (i++; i < last_entry_index; i++) {
1557bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris          delete entries_[i];
1567bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris          entries_[i] = nullptr;
1577bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris        }
1587bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris        break;
1597bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris      }
1607bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris      delete entries_[i];
1617bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris      entries_[i] = nullptr;
1627bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    }
1637bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    close(dump_fd);
1647bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1657bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    // Mark the entries dumped.
1667bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    cur_index_ = 0U;
1677bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  } else {
1687bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    error_log("Cannot create record alloc file %s: %s", dump_file_.c_str(), strerror(errno));
1697bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    // Since we couldn't create the file, reset the entries dumped back
1707bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    // to the original value.
1717bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    cur_index_ = last_entry_index;
1727bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
1737bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1747bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  dump_ = false;
1757bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
1767bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1777bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisRecordData::RecordData() {
1787bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  pthread_key_create(&key_, ThreadKeyDelete);
1797bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
1807bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1817bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisbool RecordData::Initialize(const Config& config) {
1827bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  struct sigaction dump_act;
1837bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  memset(&dump_act, 0, sizeof(dump_act));
1847bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1857bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  dump_act.sa_sigaction = RecordDump;
1867bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  dump_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK;
1877bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  sigemptyset(&dump_act.sa_mask);
1882b2b25b87827102671cdd4b25c01aa22a9971a63Christopher Ferris  if (sigaction(config.record_allocs_signal(), &dump_act, nullptr) != 0) {
1897bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    error_log("Unable to set up record dump signal function: %s", strerror(errno));
1907bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    return false;
1917bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
1927bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  pthread_setspecific(key_, nullptr);
1937bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1947bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  info_log("%s: Run: 'kill -%d %d' to dump the allocation records.", getprogname(),
1952b2b25b87827102671cdd4b25c01aa22a9971a63Christopher Ferris           config.record_allocs_signal(), getpid());
1967bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
1972b2b25b87827102671cdd4b25c01aa22a9971a63Christopher Ferris  num_entries_ = config.record_allocs_num_entries();
1987bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  entries_ = new const RecordEntry*[num_entries_];
1997bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  cur_index_ = 0;
2007bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  dump_ = false;
2012b2b25b87827102671cdd4b25c01aa22a9971a63Christopher Ferris  dump_file_ = config.record_allocs_file();
2027bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
2037bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  return true;
2047bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
2057bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
2067bd01783a830f72c1245c262a7fd9a199e90aed1Christopher FerrisRecordData::~RecordData() {
2077bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  delete [] entries_;
2087bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  pthread_key_delete(key_);
2097bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
2107bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
2117bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisvoid RecordData::AddEntryOnly(const RecordEntry* entry) {
2127bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  unsigned int entry_index = cur_index_.fetch_add(1);
2137bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  if (entry_index < num_entries_) {
2147bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    entries_[entry_index] = entry;
2157bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
2167bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
2177bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
2187bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferrisvoid RecordData::AddEntry(const RecordEntry* entry) {
2197bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  void* data = pthread_getspecific(key_);
2207bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  if (data == nullptr) {
2217bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    ThreadData* thread_data = new ThreadData(this, new ThreadCompleteEntry());
2227bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    pthread_setspecific(key_, thread_data);
2237bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
2247bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
2257bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  AddEntryOnly(entry);
2267bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris
2277bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  // Check to see if it's time to dump the entries.
2287bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  if (dump_) {
2297bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris    Dump();
2307bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris  }
2317bd01783a830f72c1245c262a7fd9a199e90aed1Christopher Ferris}
232