/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "RecordReadThread.h"

#include <sys/resource.h>
#include <unistd.h>

#include <algorithm>
#include <unordered_map>

#include "ETMRecorder.h"
#include "environment.h"
#include "event_type.h"
#include "record.h"
#include "utils.h"

namespace simpleperf {

static constexpr size_t kDefaultLowBufferLevel = 10 * kMegabyte;
static constexpr size_t kDefaultCriticalBufferLevel = 5 * kMegabyte;

RecordBuffer::RecordBuffer(size_t buffer_size)
    : read_head_(0), write_head_(0), buffer_size_(buffer_size), buffer_(new char[buffer_size]) {}

size_t RecordBuffer::GetFreeSize() const {
  size_t write_head = write_head_.load(std::memory_order_relaxed);
  size_t read_head = read_head_.load(std::memory_order_relaxed);
  size_t write_tail = read_head > 0 ? read_head - 1 : buffer_size_ - 1;
  if (write_head <= write_tail) {
    return write_tail - write_head;
  }
  return buffer_size_ - write_head + write_tail;
}

char* RecordBuffer::AllocWriteSpace(size_t record_size) {
  size_t write_head = write_head_.load(std::memory_order_relaxed);
  size_t read_head = read_head_.load(std::memory_order_acquire);
  size_t write_tail = read_head > 0 ? read_head - 1 : buffer_size_ - 1;
  cur_write_record_size_ = record_size;
  if (write_head < write_tail) {
    if (write_head + record_size > write_tail) {
      return nullptr;
    }
  } else if (write_head + record_size > buffer_size_) {
    // Not enough space at the end of the buffer, need to wrap to the start of the buffer.
    if (write_tail < record_size) {
      return nullptr;
    }
    if (buffer_size_ - write_head >= sizeof(perf_event_header)) {
      // Set the size field in perf_event_header to 0. So GetCurrentRecord() can wrap to the start
      // of the buffer when size is 0.
      memset(buffer_.get() + write_head, 0, sizeof(perf_event_header));
    }
    cur_write_record_size_ += buffer_size_ - write_head;
    write_head = 0;
  }
  return buffer_.get() + write_head;
}

void RecordBuffer::FinishWrite() {
  size_t write_head = write_head_.load(std::memory_order_relaxed);
  write_head = (write_head + cur_write_record_size_) % buffer_size_;
  write_head_.store(write_head, std::memory_order_release);
}

char* RecordBuffer::GetCurrentRecord() {
  size_t write_head = write_head_.load(std::memory_order_acquire);
  size_t read_head = read_head_.load(std::memory_order_relaxed);
  if (read_head == write_head) {
    return nullptr;
  }
  perf_event_header header;
  if (read_head > write_head) {
    if (buffer_size_ - read_head < sizeof(header) ||
        (memcpy(&header, buffer_.get() + read_head, sizeof(header)) && header.size == 0)) {
      // Need to wrap to the start of the buffer.
      cur_read_record_size_ += buffer_size_ - read_head;
      read_head = 0;
      memcpy(&header, buffer_.get(), sizeof(header));
    }
  } else {
    memcpy(&header, buffer_.get() + read_head, sizeof(header));
  }
  cur_read_record_size_ += header.size;
  return buffer_.get() + read_head;
}

void RecordBuffer::MoveToNextRecord() {
  size_t read_head = read_head_.load(std::memory_order_relaxed);
  read_head = (read_head + cur_read_record_size_) % buffer_size_;
  read_head_.store(read_head, std::memory_order_release);
  cur_read_record_size_ = 0;
}

RecordParser::RecordParser(const perf_event_attr& attr)
    : sample_type_(attr.sample_type),
      read_format_(attr.read_format),
      sample_regs_count_(__builtin_popcountll(attr.sample_regs_user)) {
  size_t pos = sizeof(perf_event_header);
  uint64_t mask = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_IP;
  pos += __builtin_popcountll(sample_type_ & mask) * sizeof(uint64_t);
  if (sample_type_ & PERF_SAMPLE_TID) {
    pid_pos_in_sample_records_ = pos;
    pos += sizeof(uint64_t);
  }
  if (sample_type_ & PERF_SAMPLE_TIME) {
    time_pos_in_sample_records_ = pos;
    pos += sizeof(uint64_t);
  }
  mask = PERF_SAMPLE_ADDR | PERF_SAMPLE_ID | PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_CPU |
         PERF_SAMPLE_PERIOD;
  pos += __builtin_popcountll(sample_type_ & mask) * sizeof(uint64_t);
  read_pos_in_sample_records_ = pos;
  if ((sample_type_ & PERF_SAMPLE_TIME) && attr.sample_id_all) {
    mask = PERF_SAMPLE_IDENTIFIER | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID | PERF_SAMPLE_ID;
    time_rpos_in_non_sample_records_ =
        (__builtin_popcountll(sample_type_ & mask) + 1) * sizeof(uint64_t);
  }
}

size_t RecordParser::GetTimePos(const perf_event_header& header) const {
  if (header.type == PERF_RECORD_SAMPLE) {
    return time_pos_in_sample_records_;
  }
  if (time_rpos_in_non_sample_records_ != 0u &&
      time_rpos_in_non_sample_records_ < header.size - sizeof(perf_event_header)) {
    return header.size - time_rpos_in_non_sample_records_;
  }
  return 0;
}

size_t RecordParser::GetStackSizePos(
    const std::function<void(size_t, size_t, void*)>& read_record_fn) const {
  size_t pos = read_pos_in_sample_records_;
  if (sample_type_ & PERF_SAMPLE_READ) {
    uint64_t nr = 1;
    if (read_format_ & PERF_FORMAT_GROUP) {
      read_record_fn(pos, sizeof(nr), &nr);
      pos += sizeof(uint64_t);
    }
    size_t u64_count = nr;
    u64_count += (read_format_ & PERF_FORMAT_TOTAL_TIME_ENABLED) ? 1 : 0;
    u64_count += (read_format_ & PERF_FORMAT_TOTAL_TIME_RUNNING) ? 1 : 0;
    u64_count += (read_format_ & PERF_FORMAT_ID) ? nr : 0;
    pos += u64_count * sizeof(uint64_t);
  }
  if (sample_type_ & PERF_SAMPLE_CALLCHAIN) {
    uint64_t ip_nr;
    read_record_fn(pos, sizeof(ip_nr), &ip_nr);
    pos += (ip_nr + 1) * sizeof(uint64_t);
  }
  if (sample_type_ & PERF_SAMPLE_RAW) {
    uint32_t size;
    read_record_fn(pos, sizeof(size), &size);
    pos += size + sizeof(uint32_t);
  }
  if (sample_type_ & PERF_SAMPLE_BRANCH_STACK) {
    uint64_t stack_nr;
    read_record_fn(pos, sizeof(stack_nr), &stack_nr);
    pos += sizeof(uint64_t) + stack_nr * sizeof(BranchStackItemType);
  }
  if (sample_type_ & PERF_SAMPLE_REGS_USER) {
    uint64_t abi;
    read_record_fn(pos, sizeof(abi), &abi);
    pos += (1 + (abi == 0 ? 0 : sample_regs_count_)) * sizeof(uint64_t);
  }
  return (sample_type_ & PERF_SAMPLE_STACK_USER) ? pos : 0;
}

KernelRecordReader::KernelRecordReader(EventFd* event_fd) : event_fd_(event_fd) {
  size_t buffer_size;
  buffer_ = event_fd_->GetMappedBuffer(buffer_size);
  buffer_mask_ = buffer_size - 1;
}

bool KernelRecordReader::GetDataFromKernelBuffer() {
  data_size_ = event_fd_->GetAvailableMmapDataSize(data_pos_);
  if (data_size_ == 0) {
    return false;
  }
  init_data_size_ = data_size_;
  record_header_.size = 0;
  return true;
}

void KernelRecordReader::ReadRecord(size_t pos, size_t size, void* dest) {
  pos = (pos + data_pos_) & buffer_mask_;
  size_t copy_size = std::min(size, buffer_mask_ + 1 - pos);
  memcpy(dest, buffer_ + pos, copy_size);
  if (copy_size < size) {
    memcpy(static_cast<char*>(dest) + copy_size, buffer_, size - copy_size);
  }
}

bool KernelRecordReader::MoveToNextRecord(const RecordParser& parser) {
  data_pos_ = (data_pos_ + record_header_.size) & buffer_mask_;
  data_size_ -= record_header_.size;
  if (data_size_ == 0) {
    event_fd_->DiscardMmapData(init_data_size_);
    init_data_size_ = 0;
    return false;
  }
  ReadRecord(0, sizeof(record_header_), &record_header_);
  size_t time_pos = parser.GetTimePos(record_header_);
  if (time_pos != 0) {
    ReadRecord(time_pos, sizeof(record_time_), &record_time_);
  }
  return true;
}

timeval ETMDataRateLimiter::GetNextReadInterval(uint64_t data_size, uint64_t timestamp) {
  // desired_time_elapsed_ns: The target elapsed time (in nanoseconds) to receive data_size bytes,
  // based on max_size_per_second_.
  uint64_t desired_time_elapsed_ns = (data_size * 1000000000) / max_size_per_second_;

  // actual_time_elapsed_ns: The actual time elapsed (in nanoseconds) since the start timestamp.
  uint64_t actual_time_elapsed_ns = timestamp - start_timestamp_;

  uint64_t read_interval_ns = min_read_interval_ns_;
  if (actual_time_elapsed_ns < desired_time_elapsed_ns) {
    read_interval_ns = std::max(read_interval_ns, desired_time_elapsed_ns - actual_time_elapsed_ns);
  }

  timeval tv;
  tv.tv_sec = read_interval_ns / 1000000000;
  tv.tv_usec = read_interval_ns % 1000000000 / 1000;
  return tv;
}

RecordReadThread::RecordReadThread(size_t record_buffer_size, const perf_event_attr& attr,
                                   size_t min_mmap_pages, size_t max_mmap_pages,
                                   size_t aux_buffer_size, bool allow_truncating_samples,
                                   bool exclude_perf, std::chrono::milliseconds etm_flush_interval)
    : record_buffer_(record_buffer_size),
      record_parser_(attr),
      attr_(attr),
      min_mmap_pages_(min_mmap_pages),
      max_mmap_pages_(max_mmap_pages),
      aux_buffer_size_(aux_buffer_size),
      // max_size_per_second is based on the ETM data generation rate from ETR-based ETM events.
      etm_data_rate_limiter_(aux_buffer_size * 1000 / etm_flush_interval.count(),
                             etm_flush_interval, GetSystemClock()) {
  if (attr.sample_type & PERF_SAMPLE_STACK_USER) {
    stack_size_in_sample_record_ = attr.sample_stack_user;
  }
  record_buffer_low_level_ = std::min(record_buffer_size / 4, kDefaultLowBufferLevel);
  record_buffer_critical_level_ = std::min(record_buffer_size / 6, kDefaultCriticalBufferLevel);
  LOG(VERBOSE) << "user buffer size = " << record_buffer_size
               << ", low_level size = " << record_buffer_low_level_
               << ", critical_level size = " << record_buffer_critical_level_;
  if (!allow_truncating_samples) {
    record_buffer_low_level_ = record_buffer_critical_level_;
  }
  if (exclude_perf) {
    exclude_pid_ = getpid();
  }
}

RecordReadThread::~RecordReadThread() {
  if (read_thread_) {
    StopReadThread();
  }
}

bool RecordReadThread::RegisterDataCallback(IOEventLoop& loop,
                                            const std::function<bool()>& data_callback) {
  int cmd_fd[2];
  int data_fd[2];
  if (pipe2(cmd_fd, O_CLOEXEC) != 0 || pipe2(data_fd, O_CLOEXEC) != 0) {
    PLOG(ERROR) << "pipe2";
    return false;
  }
  read_cmd_fd_.reset(cmd_fd[0]);
  write_cmd_fd_.reset(cmd_fd[1]);
  cmd_ = NO_CMD;
  read_data_fd_.reset(data_fd[0]);
  write_data_fd_.reset(data_fd[1]);
  has_data_notification_ = false;
  if (!loop.AddReadEvent(read_data_fd_, data_callback)) {
    return false;
  }
  read_thread_.reset(new std::thread([&]() { RunReadThread(); }));
  return true;
}

bool RecordReadThread::AddEventFds(const std::vector<EventFd*>& event_fds) {
  return SendCmdToReadThread(CMD_ADD_EVENT_FDS, const_cast<std::vector<EventFd*>*>(&event_fds));
}

bool RecordReadThread::RemoveEventFds(const std::vector<EventFd*>& event_fds) {
  return SendCmdToReadThread(CMD_REMOVE_EVENT_FDS, const_cast<std::vector<EventFd*>*>(&event_fds));
}

bool RecordReadThread::SyncKernelBuffer() {
  return SendCmdToReadThread(CMD_SYNC_KERNEL_BUFFER, nullptr);
}

bool RecordReadThread::StopReadThread() {
  bool result = true;
  if (read_thread_ != nullptr) {
    result = SendCmdToReadThread(CMD_STOP_THREAD, nullptr);
    if (result) {
      read_thread_->join();
      read_thread_ = nullptr;
    }
  }
  return result;
}

bool RecordReadThread::SendCmdToReadThread(Cmd cmd, void* cmd_arg) {
  {
    std::lock_guard<std::mutex> lock(cmd_mutex_);
    cmd_ = cmd;
    cmd_arg_ = cmd_arg;
  }
  char unused = 0;
  if (TEMP_FAILURE_RETRY(write(write_cmd_fd_, &unused, 1)) != 1) {
    return false;
  }
  std::unique_lock<std::mutex> lock(cmd_mutex_);
  while (cmd_ != NO_CMD) {
    cmd_finish_cond_.wait(lock);
  }
  return cmd_result_;
}

std::unique_ptr<Record> RecordReadThread::GetRecord() {
  record_buffer_.MoveToNextRecord();
  char* p = record_buffer_.GetCurrentRecord();
  if (p != nullptr) {
    std::unique_ptr<Record> r = ReadRecordFromBuffer(attr_, p, record_buffer_.BufferEnd());
    CHECK(r);
    if (r->type() == PERF_RECORD_AUXTRACE) {
      auto auxtrace = static_cast<AuxTraceRecord*>(r.get());
      record_buffer_.AddCurrentRecordSize(auxtrace->data->aux_size);
      auxtrace->location.addr = r->Binary() + r->size();
    }
    return r;
  }
  if (has_data_notification_) {
    char unused;
    TEMP_FAILURE_RETRY(read(read_data_fd_, &unused, 1));
    has_data_notification_ = false;
  }
  return nullptr;
}

void RecordReadThread::RunReadThread() {
  IncreaseThreadPriority();
  IOEventLoop loop;
  CHECK(loop.AddReadEvent(read_cmd_fd_, [&]() { return HandleCmd(loop); }));
  loop.RunLoop();
}

void RecordReadThread::IncreaseThreadPriority() {
  // TODO: use real time priority for root.
  rlimit rlim;
  int result = getrlimit(RLIMIT_NICE, &rlim);
  if (result == 0 && rlim.rlim_cur == 40) {
    result = setpriority(PRIO_PROCESS, gettid(), -20);
    if (result == 0) {
      LOG(VERBOSE) << "Priority of record read thread is increased";
    }
  }
}

RecordReadThread::Cmd RecordReadThread::GetCmd() {
  std::lock_guard<std::mutex> lock(cmd_mutex_);
  return cmd_;
}

bool RecordReadThread::HandleCmd(IOEventLoop& loop) {
  char unused;
  TEMP_FAILURE_RETRY(read(read_cmd_fd_, &unused, 1));
  bool result = true;
  switch (GetCmd()) {
    case CMD_ADD_EVENT_FDS:
      result = HandleAddEventFds(loop, *static_cast<std::vector<EventFd*>*>(cmd_arg_));
      break;
    case CMD_REMOVE_EVENT_FDS:
      result = HandleRemoveEventFds(*static_cast<std::vector<EventFd*>*>(cmd_arg_));
      break;
    case CMD_SYNC_KERNEL_BUFFER:
      if (has_etm_events_) {
        result = ReadETMData();
      } else {
        result = ReadRecordsFromKernelBuffer();
      }
      break;
    case CMD_STOP_THREAD:
      result = loop.ExitLoop();
      break;
    default:
      LOG(ERROR) << "Unknown cmd: " << GetCmd();
      result = false;
      break;
  }
  std::lock_guard<std::mutex> lock(cmd_mutex_);
  cmd_ = NO_CMD;
  cmd_result_ = result;
  cmd_finish_cond_.notify_one();
  return true;
}

bool RecordReadThread::HandleAddEventFds(IOEventLoop& loop, std::vector<EventFd*>& event_fds) {
  std::unordered_map<int, EventFd*> cpu_map;
  // Buffers are created only for the first event on every CPU, and since AuxBuffers are not shared,
  // the ones that require AuxBuffer need to come first.
  // Sort the events to fulfill this requirement.
  auto comp = [](const EventFd* fd1, const EventFd* fd2) {
    bool fd1_needs_aux = IsEtmEventName(fd1->EventName()) || IsSpeEventName(fd1->EventName());
    bool fd2_needs_aux = IsEtmEventName(fd2->EventName()) || IsSpeEventName(fd2->EventName());
    return (fd1_needs_aux && !fd2_needs_aux);
  };
  std::sort(event_fds.begin(), event_fds.end(), comp);
  for (size_t pages = max_mmap_pages_; pages >= min_mmap_pages_; pages >>= 1) {
    bool success = true;
    bool report_error = pages == min_mmap_pages_;
    for (EventFd* fd : event_fds) {
      auto it = cpu_map.find(fd->Cpu());
      if (it == cpu_map.end()) {
        if (!fd->CreateMappedBuffer(pages, report_error)) {
          success = false;
          break;
        }
        if (IsEtmEventName(fd->EventName()) || IsSpeEventName(fd->EventName())) {
          if (!fd->CreateAuxBuffer(aux_buffer_size_, report_error)) {
            fd->DestroyMappedBuffer();
            success = false;
            break;
          }
          has_aux_events_ = true;
          if (IsEtmEventName(fd->EventName())) {
            // Ideally we only need to periodically disable and enable event fds to flush ETM data
            // for ETR. Because TRBE has an interrupt to move ETM data automatically on buffer
            // overflow. However, TRBE driver lacks a patch of handling CPU idle. As a result, TRBE
            // can lose power in CPU idle, and we can no longer get ETM data after that. So before
            // the kernel patch is available (which is currently in review in
            // https://lists.infradead.org/pipermail/linux-arm-kernel/2025-May/1028966.html), we
            // need a workaround to also periodically disable and enable event fds for TRBE.
            etm_with_etr_fds_.push_back(fd);
            has_etm_events_ = true;
          }
        }
        cpu_map[fd->Cpu()] = fd;
      } else {
        if (!fd->ShareMappedBuffer(*(it->second), pages == min_mmap_pages_)) {
          success = false;
          break;
        }
      }
    }
    if (success) {
      LOG(VERBOSE) << "Each kernel buffer is " << pages << " pages.";
      break;
    }
    for (auto& pair : cpu_map) {
      pair.second->DestroyMappedBuffer();
      pair.second->DestroyAuxBuffer();
    }
    cpu_map.clear();
  }
  if (cpu_map.empty()) {
    return false;
  }
  for (auto& pair : cpu_map) {
    kernel_record_readers_.emplace_back(pair.second);
  }
  if (has_etm_events_) {
    // To prevent ETM data flooding from TRBE, read ETM data periodically instead of polling.
    if (!loop.AddOneTimeEvent(etm_data_rate_limiter_.GetNextReadInterval(0, GetSystemClock()),
                              [&]() { return PeriodicallyReadETMData(loop); })) {
      return false;
    }
  } else {
    for (auto& reader : kernel_record_readers_) {
      if (!reader.GetEventFd()->StartPolling(loop,
                                             [this]() { return ReadRecordsFromKernelBuffer(); })) {
        return false;
      }
    }
  }
  return true;
}

bool RecordReadThread::HandleRemoveEventFds(const std::vector<EventFd*>& event_fds) {
  for (auto& event_fd : event_fds) {
    if (event_fd->HasMappedBuffer()) {
      auto it = std::find_if(
          kernel_record_readers_.begin(), kernel_record_readers_.end(),
          [&](const KernelRecordReader& reader) { return reader.GetEventFd() == event_fd; });
      if (it != kernel_record_readers_.end()) {
        kernel_record_readers_.erase(it);
        event_fd->StopPolling();
        event_fd->DestroyMappedBuffer();
        event_fd->DestroyAuxBuffer();
      }
    }
  }
  return true;
}

// When reading from mmap buffers, we prefer reading from all buffers at once rather than reading
// one buffer at a time. Because by reading all buffers at once, we can merge records from
// different buffers easily in memory. Otherwise, we have to sort records with greater effort.
bool RecordReadThread::ReadRecordsFromKernelBuffer() {
  do {
    std::vector<KernelRecordReader*> readers;
    for (auto& reader : kernel_record_readers_) {
      if (reader.GetDataFromKernelBuffer()) {
        readers.push_back(&reader);
      }
    }
    bool has_data = false;
    if (!readers.empty()) {
      has_data = true;
      if (readers.size() == 1u) {
        // Only one buffer has data, process it directly.
        while (readers[0]->MoveToNextRecord(record_parser_)) {
          PushRecordToRecordBuffer(readers[0]);
        }
      } else {
        // Use a binary heap to merge records from different buffers. As records from the same
        // buffer are already ordered by time, we only need to merge the first record from all
        // buffers. And each time a record is popped from the heap, we put the next record from
        // its buffer into the heap.
        for (auto& reader : readers) {
          reader->MoveToNextRecord(record_parser_);
        }
        std::make_heap(readers.begin(), readers.end(), CompareRecordTime);
        size_t size = readers.size();
        while (size > 0) {
          std::pop_heap(readers.begin(), readers.begin() + size, CompareRecordTime);
          PushRecordToRecordBuffer(readers[size - 1]);
          if (readers[size - 1]->MoveToNextRecord(record_parser_)) {
            std::push_heap(readers.begin(), readers.begin() + size, CompareRecordTime);
          } else {
            size--;
          }
        }
      }
    }
    ReadAuxDataFromKernelBuffer(&has_data);
    if (!has_data) {
      break;
    }
    // Having collected everything available, this is a good time to
    // try to re-enabled any events that might have been disabled by
    // the kernel.
    for (auto event_fd : event_fds_disabled_by_kernel_) {
      event_fd->SetEnableEvent(true);
    }
    event_fds_disabled_by_kernel_.clear();
    if (!SendDataNotificationToMainThread()) {
      return false;
    }
    // If there are no commands, we can loop until there is no more data from the kernel.
    // To prevent ETM data flooding from TRBE, avoid reading ETM data in a loop.
  } while (GetCmd() == NO_CMD && !has_etm_events_);
  return true;
}

void RecordReadThread::PushRecordToRecordBuffer(KernelRecordReader* kernel_record_reader) {
  const perf_event_header& header = kernel_record_reader->RecordHeader();
  if (header.type == PERF_RECORD_SAMPLE && exclude_pid_ != -1) {
    uint32_t pid;
    kernel_record_reader->ReadRecord(record_parser_.GetPidPosInSampleRecord(), sizeof(pid), &pid);
    if (pid == exclude_pid_) {
      return;
    }
  }
  if (header.type == PERF_RECORD_SAMPLE && stack_size_in_sample_record_ > 1024) {
    size_t free_size = record_buffer_.GetFreeSize();
    if (free_size < record_buffer_critical_level_) {
      // When the free size in record buffer is below critical level, drop sample records to save
      // space for more important records (like mmap or fork records).
      stat_.userspace_lost_samples++;
      return;
    }
    size_t stack_size_limit = stack_size_in_sample_record_;
    if (free_size < record_buffer_low_level_) {
      // When the free size in record buffer is below low level, truncate the stack data in sample
      // records to 1K. This makes the unwinder unwind only part of the callchains, but hopefully
      // the call chain joiner can complete the callchains.
      stack_size_limit = 1024;
    }
    size_t stack_size_pos =
        record_parser_.GetStackSizePos([&](size_t pos, size_t size, void* dest) {
          return kernel_record_reader->ReadRecord(pos, size, dest);
        });
    uint64_t stack_size;
    kernel_record_reader->ReadRecord(stack_size_pos, sizeof(stack_size), &stack_size);
    if (stack_size > 0) {
      size_t dyn_stack_size_pos = stack_size_pos + sizeof(stack_size) + stack_size;
      uint64_t dyn_stack_size;
      kernel_record_reader->ReadRecord(dyn_stack_size_pos, sizeof(dyn_stack_size), &dyn_stack_size);
      if (dyn_stack_size == 0) {
        // If stack_user_data.dyn_size == 0, it may be because the kernel misses the patch to
        // update dyn_size, like in N9 (See b/22612370). So assume all stack data is valid if
        // dyn_size == 0.
        // TODO: Add cts test.
        dyn_stack_size = stack_size;
      }
      // When simpleperf requests the kernel to dump 64K stack per sample, it will allocate 64K
      // space in each sample to store stack data. However, a thread may use less stack than 64K.
      // So not all the 64K stack data in a sample is valid, and we only need to keep valid stack
      // data, whose size is dyn_stack_size.
      uint64_t new_stack_size = Align(std::min<uint64_t>(dyn_stack_size, stack_size_limit), 8);
      if (stack_size > new_stack_size) {
        // Remove part of the stack data.
        perf_event_header new_header = header;
        new_header.size -= stack_size - new_stack_size;
        char* p = record_buffer_.AllocWriteSpace(new_header.size);
        if (p != nullptr) {
          memcpy(p, &new_header, sizeof(new_header));
          size_t pos = sizeof(new_header);
          kernel_record_reader->ReadRecord(pos, stack_size_pos - pos, p + pos);
          memcpy(p + stack_size_pos, &new_stack_size, sizeof(uint64_t));
          pos = stack_size_pos + sizeof(uint64_t);
          kernel_record_reader->ReadRecord(pos, new_stack_size, p + pos);
          memcpy(p + pos + new_stack_size, &new_stack_size, sizeof(uint64_t));
          record_buffer_.FinishWrite();
          if (new_stack_size < dyn_stack_size) {
            stat_.userspace_truncated_stack_samples++;
          }
        } else {
          stat_.userspace_lost_samples++;
        }
        return;
      }
    }
  }
  char* p = record_buffer_.AllocWriteSpace(header.size);
  if (p != nullptr) {
    kernel_record_reader->ReadRecord(0, header.size, p);
    if (header.type == PERF_RECORD_AUX) {
      AuxRecord r;
      if (r.Parse(attr_, p, p + header.size) && (r.data->flags & PERF_AUX_FLAG_TRUNCATED)) {
        // When the kernel sees aux output flagged with PERF_AUX_FLAG_TRUNCATED,
        // it sets a pending disable on the event:
        // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/events/ring_buffer.c?h=v5.13#n516
        // The truncated flag is set by the Coresight driver when some trace was lost,
        // which can be caused by a full buffer. Therefore, try to re-enable the event
        // only after we have collected the aux data.
        event_fds_disabled_by_kernel_.insert(kernel_record_reader->GetEventFd());
      }
    } else if (header.type == PERF_RECORD_LOST) {
      LostRecord r;
      if (r.Parse(attr_, p, p + header.size)) {
        stat_.kernelspace_lost_records += static_cast<size_t>(r.lost);
      }
    }
    record_buffer_.FinishWrite();
  } else {
    if (header.type == PERF_RECORD_SAMPLE) {
      stat_.userspace_lost_samples++;
    } else {
      stat_.userspace_lost_non_samples++;
    }
  }
}

void RecordReadThread::ReadAuxDataFromKernelBuffer(bool* has_data) {
  if (!has_aux_events_) {
    return;
  }
  for (auto& reader : kernel_record_readers_) {
    EventFd* event_fd = reader.GetEventFd();
    if (event_fd->HasAuxBuffer()) {
      char* buf[2];
      size_t size[2];
      uint64_t offset = event_fd->GetAvailableAuxData(&buf[0], &size[0], &buf[1], &size[1]);
      size_t aux_size = size[0] + size[1];
      if (aux_size == 0) {
        continue;
      }
      *has_data = true;
      AuxTraceRecord auxtrace(Align(aux_size, 8), offset, event_fd->Cpu(), 0, event_fd->Cpu());
      size_t alloc_size = auxtrace.size() + auxtrace.data->aux_size;
      char* p = nullptr;
      if ((record_buffer_.GetFreeSize() < alloc_size + record_buffer_critical_level_) ||
          (p = record_buffer_.AllocWriteSpace(alloc_size)) == nullptr) {
        stat_.lost_aux_data_size += aux_size;
      } else {
        CHECK(p != nullptr);
        MoveToBinaryFormat(auxtrace.Binary(), auxtrace.size(), p);
        MoveToBinaryFormat(buf[0], size[0], p);
        if (size[1] != 0) {
          MoveToBinaryFormat(buf[1], size[1], p);
        }
        size_t pad_size = auxtrace.data->aux_size - aux_size;
        if (pad_size != 0) {
          uint64_t pad = 0;
          memcpy(p, &pad, pad_size);
        }
        record_buffer_.FinishWrite();
        stat_.aux_data_size += aux_size;
        LOG(DEBUG) << "record aux data " << aux_size << " bytes";
      }
      event_fd->DiscardAuxData(aux_size);
    }
  }
}

bool RecordReadThread::SendDataNotificationToMainThread() {
  if (has_etm_events_) {
    // For ETM recording, the default buffer size is large enough to hold ETM data for
    // several seconds. To reduce impact of processing ETM data (especially when --decode-etm is
    // used), delay processing ETM data until the buffer is half full.
    if (record_buffer_.GetFreeSize() >= record_buffer_.size() / 2) {
      return true;
    }
  }
  if (!has_data_notification_.load(std::memory_order_relaxed)) {
    has_data_notification_ = true;
    char unused = 0;
    if (TEMP_FAILURE_RETRY(write(write_data_fd_, &unused, 1)) != 1) {
      PLOG(ERROR) << "write";
      return false;
    }
  }
  return true;
}

bool RecordReadThread::PeriodicallyReadETMData(IOEventLoop& loop) {
  if (!ReadETMData()) {
    return false;
  }
  timeval read_interval =
      etm_data_rate_limiter_.GetNextReadInterval(stat_.aux_data_size, GetSystemClock());
  return loop.AddOneTimeEvent(read_interval, [&]() { return PeriodicallyReadETMData(loop); }) !=
         nullptr;
}

bool RecordReadThread::ReadETMData() {
  if (!etm_with_etr_fds_.empty()) {
    // For ETM events using ETR as the sink:
    // ETM data is dumped to kernel buffer only when there is no thread traced by ETM. It happens
    // either when all monitored threads are scheduled off cpu, or when all ETM perf events are
    // disabled. If ETM data isn't dumped to kernel buffer in time, overflow parts will be
    // dropped. This makes less than expected data, especially in system wide recording. So flush
    // ETM data by temporarily disabling all perf events.
    EventFd* last_fd = nullptr;
    for (size_t i = 0; i < etm_with_etr_fds_.size(); i++) {
      if (i == last_to_disable_etm_index_) {
        last_fd = etm_with_etr_fds_[i];
        continue;
      }
      if (!etm_with_etr_fds_[i]->SetEnableEvent(false)) {
        return false;
      }
    }
    if (!last_fd->SetEnableEvent(false)) {
      return false;
    }
    // When using ETR, ETM data is flushed to the aux buffer of the last cpu disabling ETM events.
    // To avoid overflowing the aux buffer for one cpu, rotate the last cpu disabling ETM events.
    // Disable ETM event on each cpu except for the last cpu.
    last_to_disable_etm_index_ = (last_to_disable_etm_index_ + 1) % etm_with_etr_fds_.size();

    // Enable ETM events to restart ETM tracing.
    for (auto fd : etm_with_etr_fds_) {
      if (!fd->SetEnableEvent(true)) {
        return false;
      }
    }
  }
  return ReadRecordsFromKernelBuffer();
}

}  // namespace simpleperf
