This commit adds a new option `wakeup_events` to the open_perf_buffer API.
This provides an alternative to solve #3793.
Signed-off-by: Hengqi Chen <chenhengqi@outlook.com>
void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb,
perf_reader_lost_cb lost_cb, void *cb_cookie,
- int pid, int cpu, int page_cnt) {
- int pfd;
+ int pid, int cpu, int page_cnt)
+{
+ struct bcc_perf_buffer_opts opts = {
+ .pid = pid,
+ .cpu = cpu,
+ .wakeup_events = 1,
+ };
+
+ return bpf_open_perf_buffer_opts(raw_cb, lost_cb, cb_cookie, page_cnt, &opts);
+}
+
+void * bpf_open_perf_buffer_opts(perf_reader_raw_cb raw_cb,
+ perf_reader_lost_cb lost_cb, void *cb_cookie,
+ int page_cnt, struct bcc_perf_buffer_opts *opts)
+{
+ int pfd, pid = opts->pid, cpu = opts->cpu;
struct perf_event_attr attr = {};
struct perf_reader *reader = NULL;
attr.type = PERF_TYPE_SOFTWARE;
attr.sample_type = PERF_SAMPLE_RAW;
attr.sample_period = 1;
- attr.wakeup_events = 1;
+ attr.wakeup_events = opts->wakeup_events;
pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC);
if (pfd < 0) {
fprintf(stderr, "perf_event_open: %s\n", strerror(errno));
BPF_PROBE_RETURN
};
+struct bcc_perf_buffer_opts {
+ int pid;
+ int cpu;
+ int wakeup_events;
+};
+
int bcc_create_map(enum bpf_map_type map_type, const char *name,
int key_size, int value_size, int max_entries,
int map_flags);
perf_reader_lost_cb lost_cb, void *cb_cookie,
int pid, int cpu, int page_cnt);
+void * bpf_open_perf_buffer_opts(perf_reader_raw_cb raw_cb,
+ perf_reader_lost_cb lost_cb, void *cb_cookie,
+ int page_cnt, struct bcc_perf_buffer_opts *opts);
+
/* attached a prog expressed by progfd to the device specified in dev_name */
int bpf_attach_xdp(const char *dev_name, int progfd, uint32_t flags);
lib.kernel_struct_has_field.argtypes = [ct.c_char_p, ct.c_char_p]
lib.bpf_open_perf_buffer.restype = ct.c_void_p
lib.bpf_open_perf_buffer.argtypes = [_RAW_CB_TYPE, _LOST_CB_TYPE, ct.py_object, ct.c_int, ct.c_int, ct.c_int]
+
+class bcc_perf_buffer_opts(ct.Structure):
+ _fields_ = [
+ ('pid', ct.c_int),
+ ('cpu', ct.c_int),
+ ('wakeup_events', ct.c_int),
+ ]
+
+lib.bpf_open_perf_buffer_opts.restype = ct.c_void_p
+lib.bpf_open_perf_buffer_opts.argtypes = [_RAW_CB_TYPE, _LOST_CB_TYPE, ct.py_object, ct.c_int, ct.POINTER(bcc_perf_buffer_opts)]
lib.bpf_open_perf_event.restype = ct.c_int
lib.bpf_open_perf_event.argtypes = [ct.c_uint, ct.c_ulonglong, ct.c_int, ct.c_int]
lib.perf_reader_poll.restype = ct.c_int
import re
import sys
-from .libbcc import lib, _RAW_CB_TYPE, _LOST_CB_TYPE, _RINGBUF_CB_TYPE
+from .libbcc import lib, _RAW_CB_TYPE, _LOST_CB_TYPE, _RINGBUF_CB_TYPE, bcc_perf_buffer_opts
from .utils import get_online_cpus
from .utils import get_possible_cpus
self._event_class = _get_event_class(self)
return ct.cast(data, ct.POINTER(self._event_class)).contents
- def open_perf_buffer(self, callback, page_cnt=8, lost_cb=None):
+ def open_perf_buffer(self, callback, page_cnt=8, lost_cb=None, wakeup_events=1):
"""open_perf_buffers(callback)
Opens a set of per-cpu ring buffer to receive custom perf event
raise Exception("Perf buffer page_cnt must be a power of two")
for i in get_online_cpus():
- self._open_perf_buffer(i, callback, page_cnt, lost_cb)
+ self._open_perf_buffer(i, callback, page_cnt, lost_cb, wakeup_events)
- def _open_perf_buffer(self, cpu, callback, page_cnt, lost_cb):
+ def _open_perf_buffer(self, cpu, callback, page_cnt, lost_cb, wakeup_events):
def raw_cb_(_, data, size):
try:
callback(cpu, data, size)
raise e
fn = _RAW_CB_TYPE(raw_cb_)
lost_fn = _LOST_CB_TYPE(lost_cb_) if lost_cb else ct.cast(None, _LOST_CB_TYPE)
- reader = lib.bpf_open_perf_buffer(fn, lost_fn, None, -1, cpu, page_cnt)
+ opts = bcc_perf_buffer_opts()
+ opts.pid = -1
+ opts.cpu = cpu
+ opts.wakeup_events = wakeup_events
+ reader = lib.bpf_open_perf_buffer_opts(fn, lost_fn, None, page_cnt, ct.byref(opts))
if not reader:
raise Exception("Could not open perf buffer")
fd = lib.perf_reader_fd(reader)