bcc: Allow specify wakeup_events for perf buffer
authorHengqi Chen <chenhengqi@outlook.com>
Sat, 8 Jan 2022 14:47:54 +0000 (22:47 +0800)
committerHengqi Chen <chenhengqi@outlook.com>
Sat, 8 Jan 2022 14:47:54 +0000 (22:47 +0800)
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>
src/cc/libbpf.c
src/cc/libbpf.h
src/python/bcc/libbcc.py
src/python/bcc/table.py

index 1109bac773d72724abb1b30d7ef46e1ed140d06d..63938eb5488902013ec322852a582408185ee457 100644 (file)
@@ -1408,8 +1408,22 @@ int bpf_attach_lsm(int prog_fd)
 
 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;
 
@@ -1421,7 +1435,7 @@ void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb,
   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));
index 8a49d6da58e2c00e9a236b8ab50aaea737e0c125..e001d740f3237d307df693a27360dbdacbef12b1 100644 (file)
@@ -35,6 +35,12 @@ enum bpf_probe_attach_type {
        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);
@@ -107,6 +113,10 @@ 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);
 
+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);
 
index fdea8a1265966c7ae5bee49c8c6fc721e864618d..f9b83b3cb9146b858e72e27db06c3b4b41661754 100644 (file)
@@ -133,6 +133,16 @@ lib.kernel_struct_has_field.restype = ct.c_int
 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
index f3a0ba474e62e9a7f5451b23ef9e476fb9ebecf5..6ffbfb26c2a1e91605f942145c0542544e0cf6f1 100644 (file)
@@ -25,7 +25,7 @@ import errno
 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
 
@@ -960,7 +960,7 @@ class PerfEventArray(ArrayBase):
             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
@@ -974,9 +974,9 @@ class PerfEventArray(ArrayBase):
             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)
@@ -995,7 +995,11 @@ class PerfEventArray(ArrayBase):
                     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)