Add perf_reader_consume
authorDave Marchevsky <davemarchevsky@fb.com>
Tue, 11 Jan 2022 06:30:13 +0000 (01:30 -0500)
committeryonghong-song <ys114321@gmail.com>
Tue, 11 Jan 2022 16:54:13 +0000 (08:54 -0800)
In order to read 'remainder' events from perf buffers w/ 'wakeup_events
> 1', an API to force reading from a program's perf buffers regardless
of whether their fds are in "ready to read" state is necessary. This
commit introduces such an API, perf_reader_consume, modeled after
libbpf's perf_buffer__consume.

Future work will refactor bcc to use libbpf's perf buffer
support as much as possible instead of duplicating functionality. For
now, since #3801 was commited let's add this piece of missing
functionality.

src/cc/perf_reader.c
src/cc/perf_reader.h
src/python/bcc/__init__.py
src/python/bcc/libbcc.py

index dedb11d..4bcc5fe 100644 (file)
@@ -237,6 +237,14 @@ int perf_reader_poll(int num_readers, struct perf_reader **readers, int timeout)
   return 0;
 }
 
+int perf_reader_consume(int num_readers, struct perf_reader **readers) {
+  int i;
+  for (i = 0; i < num_readers; ++i) {
+    perf_reader_event_read(readers[i]);
+  }
+  return 0;
+}
+
 void perf_reader_set_fd(struct perf_reader *reader, int fd) {
   reader->fd = fd;
 }
index dbe9cfb..278b885 100644 (file)
@@ -32,6 +32,7 @@ void perf_reader_free(void *ptr);
 int perf_reader_mmap(struct perf_reader *reader);
 void perf_reader_event_read(struct perf_reader *reader);
 int perf_reader_poll(int num_readers, struct perf_reader **readers, int timeout);
+int perf_reader_consume(int num_readers, struct perf_reader **readers);
 int perf_reader_fd(struct perf_reader *reader);
 void perf_reader_set_fd(struct perf_reader *reader, int fd);
 
index 2ff5cf0..f1900a3 100644 (file)
@@ -1667,6 +1667,18 @@ class BPF(object):
             readers[i] = v
         lib.perf_reader_poll(len(readers), readers, timeout)
 
+    def perf_buffer_consume(self):
+        """perf_buffer_consume(self)
+
+        Consume all open perf buffers, regardless of whether or not
+        they currently contain events data. Necessary to catch 'remainder'
+        events when wakeup_events > 1 is set in open_perf_buffer
+        """
+        readers = (ct.c_void_p * len(self.perf_buffers))()
+        for i, v in enumerate(self.perf_buffers.values()):
+            readers[i] = v
+        lib.perf_reader_consume(len(readers), readers)
+
     def kprobe_poll(self, timeout = -1):
         """kprobe_poll(self)
 
index f9b83b3..27076f4 100644 (file)
@@ -147,6 +147,8 @@ 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
 lib.perf_reader_poll.argtypes = [ct.c_int, ct.POINTER(ct.c_void_p), ct.c_int]
+lib.perf_reader_consume.restype = ct.c_int
+lib.perf_reader_consume.argtypes = [ct.c_int, ct.POINTER(ct.c_void_p)]
 lib.perf_reader_free.restype = None
 lib.perf_reader_free.argtypes = [ct.c_void_p]
 lib.perf_reader_fd.restype = int