Skip to content

Commit

Permalink
Merge pull request #392 from iovisor/fix_perf_buffer
Browse files Browse the repository at this point in the history
Fix breakage in open_perf_buffer
  • Loading branch information
4ast committed Feb 17, 2016
2 parents fe03606 + 0dd2441 commit aaeea7b
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 16 deletions.
10 changes: 3 additions & 7 deletions src/cc/libbpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ int bpf_detach_uprobe(const char *event_desc) {
}

void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, void *cb_cookie, int pid, int cpu) {
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0)
int pfd;
struct perf_event_attr attr = {};
struct perf_reader *reader = NULL;
Expand All @@ -358,14 +357,15 @@ void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, void *cb_cookie, int pid,
if (!reader)
goto error;

attr.config = PERF_COUNT_SW_BPF_OUTPUT;
attr.config = 10;//PERF_COUNT_SW_BPF_OUTPUT;
attr.type = PERF_TYPE_SOFTWARE;
attr.sample_type = PERF_SAMPLE_RAW;
attr.sample_period = 1;
attr.wakeup_events = 1;
pfd = syscall(__NR_perf_event_open, &attr, pid, cpu, -1, PERF_FLAG_FD_CLOEXEC);
if (pfd < 0) {
perror("perf_event_open");
fprintf(stderr, "perf_event_open: %s\n", strerror(errno));
fprintf(stderr, " (check your kernel for PERF_COUNT_SW_BPF_OUTPUT support, 4.4 or newer)\n");
goto error;
}
perf_reader_set_fd(reader, pfd);
Expand All @@ -385,8 +385,4 @@ void * bpf_open_perf_buffer(perf_reader_raw_cb raw_cb, void *cb_cookie, int pid,
perf_reader_free(reader);

return NULL;
#else
fprintf(stderr, "PERF_COUNT_SW_BPF_OUTPUT feature unsupported\n");
return NULL;
#endif
}
5 changes: 5 additions & 0 deletions src/python/bcc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,11 @@ def attach_kprobe(self, event="", fn_name="", event_re="",
open_kprobes[ev_name] = res
return self

@staticmethod
def open_kprobes():
global open_kprobes
return open_kprobes

@staticmethod
def detach_kprobe(event):
ev_name = "p_" + event.replace("+", "_").replace(".", "_")
Expand Down
7 changes: 4 additions & 3 deletions src/python/bcc/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from collections import MutableMapping
import ctypes as ct
import multiprocessing

from .libbcc import lib, _RAW_CB_TYPE

Expand Down Expand Up @@ -378,13 +379,13 @@ def _open_perf_buffer(self, cpu, callback):
raise Exception("Could not open perf buffer")
fd = lib.perf_reader_fd(reader)
self[self.Key(cpu)] = self.Leaf(fd)
open_kprobes[(id(self), cpu)] = reader
self.bpf.open_kprobes()[(id(self), cpu)] = reader
# keep a refcnt
self._cbs[cpu] = fn

def close_perf_buffer(self, key):
reader = open_kprobes.get((id(self), key))
reader = self.bpf.open_kprobes().get((id(self), key))
if reader:
lib.perf_reader_free(reader)
del(open_kprobes[(id(self), key)])
del(self.bpf.open_kprobes()[(id(self), key)])
del self._cbs[key]
39 changes: 33 additions & 6 deletions tests/cc/test_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Licensed under the Apache License, Version 2.0 (the "License")

from bcc import BPF
from ctypes import c_int, c_ulonglong
import ctypes as ct
import random
import time
from unittest import main, TestCase
Expand All @@ -12,8 +12,8 @@ class TestArray(TestCase):
def test_simple(self):
b = BPF(text="""BPF_TABLE("array", int, u64, table1, 128);""")
t1 = b["table1"]
t1[c_int(0)] = c_ulonglong(100)
t1[c_int(127)] = c_ulonglong(1000)
t1[ct.c_int(0)] = ct.c_ulonglong(100)
t1[ct.c_int(127)] = ct.c_ulonglong(1000)
for i, v in t1.items():
if i.value == 0:
self.assertEqual(v.value, 100)
Expand All @@ -24,9 +24,9 @@ def test_simple(self):
def test_native_type(self):
b = BPF(text="""BPF_TABLE("array", int, u64, table1, 128);""")
t1 = b["table1"]
t1[0] = c_ulonglong(100)
t1[-2] = c_ulonglong(37)
t1[127] = c_ulonglong(1000)
t1[0] = ct.c_ulonglong(100)
t1[-2] = ct.c_ulonglong(37)
t1[127] = ct.c_ulonglong(1000)
for i, v in t1.items():
if i.value == 0:
self.assertEqual(v.value, 100)
Expand All @@ -36,5 +36,32 @@ def test_native_type(self):
self.assertEqual(t1[-2].value, 37)
self.assertEqual(t1[-1].value, t1[127].value)

def test_perf_buffer(self):
self.counter = 0

class Data(ct.Structure):
_fields_ = [("ts", ct.c_ulonglong)]

def cb(cpu, data, size):
self.assertGreater(size, ct.sizeof(Data))
event = ct.cast(data, ct.POINTER(Data)).contents
self.counter += 1

text = """
BPF_PERF_OUTPUT(events);
int kprobe__sys_nanosleep(void *ctx) {
struct {
u64 ts;
} data = {bpf_ktime_get_ns()};
events.perf_submit(ctx, &data, sizeof(data));
return 0;
}
"""
b = BPF(text=text)
b["events"].open_perf_buffer(cb)
time.sleep(0.1)
b.kprobe_poll()
self.assertGreater(self.counter, 0)

if __name__ == "__main__":
main()

0 comments on commit aaeea7b

Please sign in to comment.