Commit 1e5971d5 authored by 4ast's avatar 4ast Committed by GitHub

Merge pull request #846 from palmtenor/improve_buffer

Improve C++ API perf buffer polling
parents a3ddcd59 cae072ae
...@@ -30,6 +30,7 @@ struct urandom_read_args { ...@@ -30,6 +30,7 @@ struct urandom_read_args {
struct event_t { struct event_t {
int pid; int pid;
char comm[16]; char comm[16];
int cpu;
int got_bits; int got_bits;
}; };
...@@ -39,6 +40,7 @@ int on_urandom_read(struct urandom_read_args* attr) { ...@@ -39,6 +40,7 @@ int on_urandom_read(struct urandom_read_args* attr) {
struct event_t event = {}; struct event_t event = {};
event.pid = bpf_get_current_pid_tgid(); event.pid = bpf_get_current_pid_tgid();
bpf_get_current_comm(&event.comm, sizeof(event.comm)); bpf_get_current_comm(&event.comm, sizeof(event.comm));
event.cpu = bpf_get_smp_processor_id();
event.got_bits = attr->got_bits; event.got_bits = attr->got_bits;
events.perf_submit(attr, &event, sizeof(event)); events.perf_submit(attr, &event, sizeof(event));
...@@ -50,13 +52,15 @@ int on_urandom_read(struct urandom_read_args* attr) { ...@@ -50,13 +52,15 @@ int on_urandom_read(struct urandom_read_args* attr) {
struct event_t { struct event_t {
int pid; int pid;
char comm[16]; char comm[16];
int cpu;
int got_bits; int got_bits;
}; };
void handle_output(void* cb_cookie, void* data, int data_size) { void handle_output(void* cb_cookie, void* data, int data_size) {
auto event = static_cast<event_t*>(data); auto event = static_cast<event_t*>(data);
std::cout << "PID: " << event->pid << " (" << event->comm << ") " std::cout << "PID: " << event->pid << " (" << event->comm << ") on CPU "
<< "Read " << event->got_bits << " bits" << std::endl; << event->cpu << " read " << event->got_bits << " bits"
<< std::endl;
} }
ebpf::BPF* bpf; ebpf::BPF* bpf;
......
...@@ -98,7 +98,7 @@ StatusTuple BPF::detach_all() { ...@@ -98,7 +98,7 @@ StatusTuple BPF::detach_all() {
} }
for (auto it : perf_buffers_) { for (auto it : perf_buffers_) {
auto res = it.second->close(); auto res = it.second->close_all_cpu();
if (res.code() != 0) { if (res.code() != 0) {
error_msg += "Failed to close perf buffer " + it.first + ": "; error_msg += "Failed to close perf buffer " + it.first + ": ";
error_msg += res.msg() + "\n"; error_msg += res.msg() + "\n";
...@@ -279,7 +279,7 @@ StatusTuple BPF::open_perf_buffer(const std::string& name, ...@@ -279,7 +279,7 @@ StatusTuple BPF::open_perf_buffer(const std::string& name,
if (perf_buffers_.find(name) == perf_buffers_.end()) if (perf_buffers_.find(name) == perf_buffers_.end())
perf_buffers_[name] = new BPFPerfBuffer(bpf_module_.get(), name); perf_buffers_[name] = new BPFPerfBuffer(bpf_module_.get(), name);
auto table = perf_buffers_[name]; auto table = perf_buffers_[name];
TRY2(table->open(cb, cb_cookie)); TRY2(table->open_all_cpu(cb, cb_cookie));
return StatusTuple(0); return StatusTuple(0);
} }
...@@ -287,7 +287,7 @@ StatusTuple BPF::close_perf_buffer(const std::string& name) { ...@@ -287,7 +287,7 @@ StatusTuple BPF::close_perf_buffer(const std::string& name) {
auto it = perf_buffers_.find(name); auto it = perf_buffers_.find(name);
if (it == perf_buffers_.end()) if (it == perf_buffers_.end())
return StatusTuple(-1, "Perf buffer for %s not open", name.c_str()); return StatusTuple(-1, "Perf buffer for %s not open", name.c_str());
TRY2(it->second->close()); TRY2(it->second->close_all_cpu());
return StatusTuple(0); return StatusTuple(0);
} }
......
...@@ -79,13 +79,23 @@ StatusTuple BPFPerfBuffer::open_on_cpu(perf_reader_raw_cb cb, int cpu, ...@@ -79,13 +79,23 @@ StatusTuple BPFPerfBuffer::open_on_cpu(perf_reader_raw_cb cb, int cpu,
return StatusTuple(-1, "Unable to open perf buffer on CPU %d: %s", cpu, return StatusTuple(-1, "Unable to open perf buffer on CPU %d: %s", cpu,
strerror(errno)); strerror(errno));
} }
cpu_readers_[cpu] = static_cast<perf_reader*>(reader); cpu_readers_[cpu] = reader;
readers_.push_back(reader);
return StatusTuple(0); return StatusTuple(0);
} }
StatusTuple BPFPerfBuffer::open(perf_reader_raw_cb cb, void* cb_cookie) { StatusTuple BPFPerfBuffer::open_all_cpu(perf_reader_raw_cb cb,
for (int i = 0; i < sysconf(_SC_NPROCESSORS_ONLN); i++) void* cb_cookie) {
TRY2(open_on_cpu(cb, i, cb_cookie)); if (cpu_readers_.size() != 0 || readers_.size() != 0)
return StatusTuple(-1, "Previously opened perf buffer not cleaned");
for (int i = 0; i < sysconf(_SC_NPROCESSORS_ONLN); i++) {
auto res = open_on_cpu(cb, i, cb_cookie);
if (res.code() != 0) {
TRY2(close_all_cpu());
return res;
}
}
return StatusTuple(0); return StatusTuple(0);
} }
...@@ -100,7 +110,7 @@ StatusTuple BPFPerfBuffer::close_on_cpu(int cpu) { ...@@ -100,7 +110,7 @@ StatusTuple BPFPerfBuffer::close_on_cpu(int cpu) {
return StatusTuple(0); return StatusTuple(0);
} }
StatusTuple BPFPerfBuffer::close() { StatusTuple BPFPerfBuffer::close_all_cpu() {
std::string errors; std::string errors;
bool has_error = false; bool has_error = false;
for (int i = 0; i < sysconf(_SC_NPROCESSORS_ONLN); i++) { for (int i = 0; i < sysconf(_SC_NPROCESSORS_ONLN); i++) {
...@@ -111,21 +121,20 @@ StatusTuple BPFPerfBuffer::close() { ...@@ -111,21 +121,20 @@ StatusTuple BPFPerfBuffer::close() {
has_error = true; has_error = true;
} }
} }
readers_.clear();
if (has_error) if (has_error)
return StatusTuple(-1, errors); return StatusTuple(-1, errors);
return StatusTuple(0); return StatusTuple(0);
} }
void BPFPerfBuffer::poll(int timeout) { void BPFPerfBuffer::poll(int timeout) {
perf_reader* readers[cpu_readers_.size()]; if (readers_.empty())
int i = 0; return;
for (auto it : cpu_readers_) perf_reader_poll(readers_.size(), readers_.data(), timeout);
readers[i++] = it.second;
perf_reader_poll(cpu_readers_.size(), readers, timeout);
} }
BPFPerfBuffer::~BPFPerfBuffer() { BPFPerfBuffer::~BPFPerfBuffer() {
auto res = close(); auto res = close_all_cpu();
if (res.code() != 0) if (res.code() != 0)
std::cerr << "Failed to close all perf buffer on destruction: " std::cerr << "Failed to close all perf buffer on destruction: "
<< res.msg() << std::endl; << res.msg() << std::endl;
......
...@@ -126,8 +126,8 @@ public: ...@@ -126,8 +126,8 @@ public:
: BPFTableBase<int, int>(bpf_module, name) {} : BPFTableBase<int, int>(bpf_module, name) {}
~BPFPerfBuffer(); ~BPFPerfBuffer();
StatusTuple open(perf_reader_raw_cb cb, void* cb_cookie); StatusTuple open_all_cpu(perf_reader_raw_cb cb, void* cb_cookie);
StatusTuple close(); StatusTuple close_all_cpu();
void poll(int timeout); void poll(int timeout);
private: private:
...@@ -135,6 +135,7 @@ private: ...@@ -135,6 +135,7 @@ private:
StatusTuple close_on_cpu(int cpu); StatusTuple close_on_cpu(int cpu);
std::map<int, perf_reader*> cpu_readers_; std::map<int, perf_reader*> cpu_readers_;
std::vector<perf_reader*> readers_;
}; };
} // namespace ebpf } // namespace ebpf
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment