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;
}