mirror of
https://github.com/varun-r-mallya/pylibbpf.git
synced 2026-02-09 14:40:55 +00:00
Add parser and parent shared_ptr to PerfEventArray
This commit is contained in:
@ -1,37 +0,0 @@
|
||||
#ifndef PYLIBBPF_PERF_EVENT_ARRAY_H
|
||||
#define PYLIBBPF_PERF_EVENT_ARRAY_H
|
||||
|
||||
#include <libbpf.h>
|
||||
#include <pybind11/functional.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <string>
|
||||
|
||||
class StructParser;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
class PerfEventArray {
|
||||
private:
|
||||
struct perf_buffer *pb_;
|
||||
py::function callback_;
|
||||
py::function lost_callback_;
|
||||
|
||||
std::shared_ptr<StructParser> parser_;
|
||||
std::string struct_name_;
|
||||
|
||||
// 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:
|
||||
PerfEventArray(int map_fd, int page_cnt, py::function callback,
|
||||
py::object lost_callback = py::none());
|
||||
~PerfEventArray();
|
||||
|
||||
int poll(int timeout_ms);
|
||||
int consume();
|
||||
[[nodiscard]] int fd() const;
|
||||
};
|
||||
|
||||
#endif // PYLIBBPF_PERF_EVENT_ARRAY_H
|
||||
@ -1,11 +1,17 @@
|
||||
#include "perf_event_array.h"
|
||||
#include "core/bpf_exception.h"
|
||||
#include "core/bpf_map.h"
|
||||
|
||||
PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
|
||||
py::object lost_callback)
|
||||
: pb_(nullptr), callback_(std::move(callback)),
|
||||
PerfEventArray::PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
|
||||
py::function callback, py::object lost_callback)
|
||||
: map_(map), pb_(nullptr), callback_(std::move(callback)),
|
||||
lost_callback_(lost_callback) {
|
||||
|
||||
if (map->get_type() != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
|
||||
throw BpfException("Map '" + map->get_name() +
|
||||
"' is not a PERF_EVENT_ARRAY");
|
||||
}
|
||||
|
||||
if (page_cnt <= 0 || (page_cnt & (page_cnt - 1)) != 0) {
|
||||
throw BpfException("page_cnt must be a positive power of 2");
|
||||
}
|
||||
@ -14,7 +20,7 @@ PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
|
||||
pb_opts.sz = sizeof(pb_opts); // Required for forward compatibility
|
||||
|
||||
pb_ = perf_buffer__new(
|
||||
map_fd, page_cnt,
|
||||
map->get_fd(), page_cnt,
|
||||
sample_callback_wrapper, // sample_cb
|
||||
lost_callback.is_none() ? nullptr : lost_callback_wrapper, // lost_cb
|
||||
this, // ctx
|
||||
@ -27,6 +33,25 @@ PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
|
||||
}
|
||||
}
|
||||
|
||||
PerfEventArray::PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
|
||||
py::function callback,
|
||||
const std::string &struct_name,
|
||||
py::object lost_callback)
|
||||
: PerfEventArray(map, page_cnt, callback, lost_callback) {
|
||||
|
||||
auto parent = map->get_parent();
|
||||
if (!parent) {
|
||||
throw BpfException("Parent BpfObject has been destroyed");
|
||||
}
|
||||
|
||||
parser_ = parent->get_struct_parser();
|
||||
struct_name_ = struct_name;
|
||||
|
||||
if (!parser_) {
|
||||
throw BpfException("No struct definitions available");
|
||||
}
|
||||
}
|
||||
|
||||
PerfEventArray::~PerfEventArray() {
|
||||
if (pb_) {
|
||||
perf_buffer__free(pb_);
|
||||
@ -34,7 +59,7 @@ PerfEventArray::~PerfEventArray() {
|
||||
}
|
||||
|
||||
void PerfEventArray::sample_callback_wrapper(void *ctx, int cpu, void *data,
|
||||
unsigned int size) {
|
||||
unsigned int size) {
|
||||
auto *self = static_cast<PerfEventArray *>(ctx);
|
||||
|
||||
// Acquire GIL for Python calls
|
||||
@ -44,15 +69,23 @@ void PerfEventArray::sample_callback_wrapper(void *ctx, int cpu, void *data,
|
||||
// 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);
|
||||
if (self->parser_ && !self->struct_name_.empty()) {
|
||||
py::object event = self->parser_->parse(self->struct_name_, py_data);
|
||||
self->callback_(cpu, event);
|
||||
} else {
|
||||
self->callback_(cpu, py_data);
|
||||
}
|
||||
|
||||
} catch (const py::error_already_set &e) {
|
||||
PyErr_Print();
|
||||
} catch (const std::exception &e) {
|
||||
py::gil_scoped_acquire acquire;
|
||||
py::print("C++ error in perf callback:", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void PerfEventArray::lost_callback_wrapper(void *ctx, int cpu,
|
||||
unsigned long long cnt) {
|
||||
unsigned long long cnt) {
|
||||
auto *self = static_cast<PerfEventArray *>(ctx);
|
||||
|
||||
if (self->lost_callback_.is_none()) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#ifndef PYLIBBPF_BPF_PERF_BUFFER_H
|
||||
#define PYLIBBPF_BPF_PERF_BUFFER_H
|
||||
#ifndef PYLIBBPF_PERF_EVENT_ARRAY_H
|
||||
#define PYLIBBPF_PERF_EVENT_ARRAY_H
|
||||
|
||||
#include <libbpf.h>
|
||||
#include <pybind11/functional.h>
|
||||
@ -7,11 +7,13 @@
|
||||
#include <string>
|
||||
|
||||
class StructParser;
|
||||
class BpfMap;
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
class PerfEventArray {
|
||||
private:
|
||||
std::shared_ptr<BpfMap> map_;
|
||||
struct perf_buffer *pb_;
|
||||
py::function callback_;
|
||||
py::function lost_callback_;
|
||||
@ -25,13 +27,20 @@ private:
|
||||
static void lost_callback_wrapper(void *ctx, int cpu, unsigned long long cnt);
|
||||
|
||||
public:
|
||||
PerfEventArray(int map_fd, int page_cnt, py::function callback,
|
||||
py::object lost_callback = py::none());
|
||||
PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
|
||||
py::function callback, py::object lost_callback = py::none());
|
||||
PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
|
||||
py::function callback, const std::string &struct_name,
|
||||
py::object lost_callback = py::none());
|
||||
~PerfEventArray();
|
||||
|
||||
PerfEventArray(const PerfEventArray &) = delete;
|
||||
PerfEventArray &operator=(const PerfEventArray &) = delete;
|
||||
|
||||
int poll(int timeout_ms);
|
||||
int consume();
|
||||
[[nodiscard]] int fd() const;
|
||||
|
||||
[[nodiscard]] std::shared_ptr<BpfMap> get_map() const { return map_; }
|
||||
};
|
||||
|
||||
#endif // PYLIBBPF_BPF_PERF_BUFFER_H
|
||||
#endif // PYLIBBPF_PERF_EVENT_ARRAY_H
|
||||
|
||||
Reference in New Issue
Block a user