void BpfAdapter::handlePerfEvent()

in katran/lib/BpfAdapter.cpp [765:829]


void BpfAdapter::handlePerfEvent(
    folly::Function<void(const char* data, size_t size)> eventHandler,
    struct perf_event_mmap_page* header,
    std::string& buffer,
    int pageSize,
    int pages,
    int cpu) {
  if (header == nullptr) {
    VLOG(2) << "handlePerfEvent: unexpectedly header equals to nullptr";
    return;
  }
  auto dataTail = header->data_tail;
  auto dataHead = header->data_head;
  auto bufferSize = pageSize * pages;
  char *base, *begin, *end;

  asm volatile("" ::: "memory"); /* smp_rmb() */
  if (dataHead == dataTail) {
    return;
  }

  base = reinterpret_cast<char*>(header) + pageSize;

  begin = base + dataTail % bufferSize;
  end = base + dataHead % bufferSize;

  while (begin != end) {
    const struct perf_event_sample* event;

    event = reinterpret_cast<const struct perf_event_sample*>(begin);
    if (begin + event->header.size > base + bufferSize) {
      long len = base + bufferSize - begin;

      CHECK_LT(len, event->header.size);
      if (event->header.size > buffer.size()) {
        buffer.resize(event->header.size);
      }
      buffer.assign(begin, len);
      buffer.insert(len, base, event->header.size - len);
      event = reinterpret_cast<const struct perf_event_sample*>(buffer.data());
      begin = base + event->header.size - len;
    } else if (begin + event->header.size == base + bufferSize) {
      begin = base;
    } else {
      begin += event->header.size;
    }

    if (event->header.type == PERF_RECORD_SAMPLE) {
      eventHandler(event->data, event->size);
    } else if (event->header.type == PERF_RECORD_LOST) {
      const struct lost_sample {
        struct perf_event_header header;
        __u64 id;
        __u64 lost;
      }* lost = reinterpret_cast<const struct lost_sample*>(event);
      VLOG(5) << "cpu:" << cpu << " lost " << lost->lost << " events";
    } else {
      VLOG(5) << "cpu:" << cpu
              << " received unknown event type:" << event->header.type
              << " size:" << event->header.size;
    }
  }
  __sync_synchronize(); /* smp_mb() */
  header->data_tail = dataHead;
}