Add src/core/bpf_perf_buffer

This commit is contained in:
Pragyansh Chaturvedi
2025-10-17 03:47:31 +05:30
parent 5a3937b7f6
commit 8d27a351e0
2 changed files with 100 additions and 0 deletions

View File

@ -0,0 +1,72 @@
#include "bpf_perf_buffer.h"
#include "bpf_exception.h"
void BpfPerfBuffer::sample_callback_wrapper(void *ctx, int cpu, void *data, unsigned int size) {
auto *self = static_cast<BpfPerfBuffer *>(ctx);
// Acquire GIL for Python calls
py::gil_scoped_acquire acquire;
try {
// Convert data to Python bytes
py::bytes py_data(static_cast<const char *>(data), size);
// Call Python callback: callback(cpu, data, size)
self->callback_(cpu, py_data, size);
} catch (const py::error_already_set &e) {
PyErr_Print();
}
}
void BpfPerfBuffer::lost_callback_wrapper(void *ctx, int cpu, unsigned long long cnt) {
auto *self = static_cast<BpfPerfBuffer *>(ctx);
if (self->lost_callback_.is_none()) {
return;
}
py::gil_scoped_acquire acquire;
try {
self->lost_callback_(cpu, cnt);
} catch (const py::error_already_set &e) {
PyErr_Print();
}
}
BpfPerfBuffer::BpfPerfBuffer(int map_fd, int page_cnt, py::function callback, py::object lost_callback)
: pb_(nullptr), callback_(std::move(callback)) {
if (!lost_callback.is_none()) {
lost_callback_ = lost_callback.cast<py::function>();
}
// Setup perf buffer options
perf_buffer_opts pb_opts = {};
pb_opts.sample_cb = sample_callback_wrapper;
pb_opts.lost_cb = lost_callback.is_none() ? nullptr : lost_callback_wrapper;
pb_opts.ctx = this;
// Create perf buffer
pb_ = perf_buffer__new(map_fd, page_cnt, &pb_opts);
if (!pb_) {
throw BpfException("Failed to create perf buffer");
}
}
BpfPerfBuffer::~BpfPerfBuffer() {
if (pb_) {
perf_buffer__free(pb_);
}
}
int BpfPerfBuffer::poll(int timeout_ms) {
// Release GIL during blocking poll
py::gil_scoped_release release;
return perf_buffer__poll(pb_, timeout_ms);
}
int BpfPerfBuffer::consume() {
py::gil_scoped_release release;
return perf_buffer__consume(pb_);
}

View File

@ -0,0 +1,28 @@
#ifndef PYLIBBPF_BPF_PERF_BUFFER_H
#define PYLIBBPF_BPF_PERF_BUFFER_H
#include <libbpf.h>
#include <pybind11/pybind11.h>
#include <pybind11/functional.h>
namespace py = pybind11;
class BpfPerfBuffer {
private:
struct perf_buffer *pb_;
py::function callback_;
py::function lost_callback_;
// Static callback wrappers for C API
static void sample_callback_wrapper(void *ctx, int cpu, void *data, unsigned int size);
static void lost_callback_wrapper(void *ctx, int cpu, unsigned long long cnt);
public:
BpfPerfBuffer(int map_fd, int page_cnt, py::function callback, py::object lost_callback);
~BpfPerfBuffer();
int poll(int timeout_ms);
int consume();
};
#endif // PYLIBBPF_BPF_PERF_BUFFER_H