Skip to content

Commit 8babf30

Browse files
committed
Add parser and parent shared_ptr to PerfEventArray
1 parent cbfe6ae commit 8babf30

File tree

3 files changed

+56
-51
lines changed

3 files changed

+56
-51
lines changed

src/maps/bpf_perf_buffer.h

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/maps/perf_event_array.cpp

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
#include "perf_event_array.h"
22
#include "core/bpf_exception.h"
3+
#include "core/bpf_map.h"
34

4-
PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
5-
py::object lost_callback)
6-
: pb_(nullptr), callback_(std::move(callback)),
5+
PerfEventArray::PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
6+
py::function callback, py::object lost_callback)
7+
: map_(map), pb_(nullptr), callback_(std::move(callback)),
78
lost_callback_(lost_callback) {
89

10+
if (map->get_type() != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
11+
throw BpfException("Map '" + map->get_name() +
12+
"' is not a PERF_EVENT_ARRAY");
13+
}
14+
915
if (page_cnt <= 0 || (page_cnt & (page_cnt - 1)) != 0) {
1016
throw BpfException("page_cnt must be a positive power of 2");
1117
}
@@ -14,7 +20,7 @@ PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
1420
pb_opts.sz = sizeof(pb_opts); // Required for forward compatibility
1521

1622
pb_ = perf_buffer__new(
17-
map_fd, page_cnt,
23+
map->get_fd(), page_cnt,
1824
sample_callback_wrapper, // sample_cb
1925
lost_callback.is_none() ? nullptr : lost_callback_wrapper, // lost_cb
2026
this, // ctx
@@ -27,14 +33,33 @@ PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
2733
}
2834
}
2935

36+
PerfEventArray::PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
37+
py::function callback,
38+
const std::string &struct_name,
39+
py::object lost_callback)
40+
: PerfEventArray(map, page_cnt, callback, lost_callback) {
41+
42+
auto parent = map->get_parent();
43+
if (!parent) {
44+
throw BpfException("Parent BpfObject has been destroyed");
45+
}
46+
47+
parser_ = parent->get_struct_parser();
48+
struct_name_ = struct_name;
49+
50+
if (!parser_) {
51+
throw BpfException("No struct definitions available");
52+
}
53+
}
54+
3055
PerfEventArray::~PerfEventArray() {
3156
if (pb_) {
3257
perf_buffer__free(pb_);
3358
}
3459
}
3560

3661
void PerfEventArray::sample_callback_wrapper(void *ctx, int cpu, void *data,
37-
unsigned int size) {
62+
unsigned int size) {
3863
auto *self = static_cast<PerfEventArray *>(ctx);
3964

4065
// Acquire GIL for Python calls
@@ -44,15 +69,23 @@ void PerfEventArray::sample_callback_wrapper(void *ctx, int cpu, void *data,
4469
// Convert data to Python bytes
4570
py::bytes py_data(static_cast<const char *>(data), size);
4671

47-
// Call Python callback: callback(cpu, data, size)
48-
self->callback_(cpu, py_data, size);
72+
if (self->parser_ && !self->struct_name_.empty()) {
73+
py::object event = self->parser_->parse(self->struct_name_, py_data);
74+
self->callback_(cpu, event);
75+
} else {
76+
self->callback_(cpu, py_data);
77+
}
78+
4979
} catch (const py::error_already_set &e) {
5080
PyErr_Print();
81+
} catch (const std::exception &e) {
82+
py::gil_scoped_acquire acquire;
83+
py::print("C++ error in perf callback:", e.what());
5184
}
5285
}
5386

5487
void PerfEventArray::lost_callback_wrapper(void *ctx, int cpu,
55-
unsigned long long cnt) {
88+
unsigned long long cnt) {
5689
auto *self = static_cast<PerfEventArray *>(ctx);
5790

5891
if (self->lost_callback_.is_none()) {

src/maps/perf_event_array.h

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
#ifndef PYLIBBPF_BPF_PERF_BUFFER_H
2-
#define PYLIBBPF_BPF_PERF_BUFFER_H
1+
#ifndef PYLIBBPF_PERF_EVENT_ARRAY_H
2+
#define PYLIBBPF_PERF_EVENT_ARRAY_H
33

44
#include <libbpf.h>
55
#include <pybind11/functional.h>
66
#include <pybind11/pybind11.h>
77
#include <string>
88

99
class StructParser;
10+
class BpfMap;
1011

1112
namespace py = pybind11;
1213

1314
class PerfEventArray {
1415
private:
16+
std::shared_ptr<BpfMap> map_;
1517
struct perf_buffer *pb_;
1618
py::function callback_;
1719
py::function lost_callback_;
@@ -25,13 +27,20 @@ class PerfEventArray {
2527
static void lost_callback_wrapper(void *ctx, int cpu, unsigned long long cnt);
2628

2729
public:
28-
PerfEventArray(int map_fd, int page_cnt, py::function callback,
29-
py::object lost_callback = py::none());
30+
PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
31+
py::function callback, py::object lost_callback = py::none());
32+
PerfEventArray(std::shared_ptr<BpfMap> map, int page_cnt,
33+
py::function callback, const std::string &struct_name,
34+
py::object lost_callback = py::none());
3035
~PerfEventArray();
3136

37+
PerfEventArray(const PerfEventArray &) = delete;
38+
PerfEventArray &operator=(const PerfEventArray &) = delete;
39+
3240
int poll(int timeout_ms);
3341
int consume();
34-
[[nodiscard]] int fd() const;
42+
43+
[[nodiscard]] std::shared_ptr<BpfMap> get_map() const { return map_; }
3544
};
3645

37-
#endif // PYLIBBPF_BPF_PERF_BUFFER_H
46+
#endif // PYLIBBPF_PERF_EVENT_ARRAY_H

0 commit comments

Comments
 (0)