Skip to content

Commit

Permalink
add interval probe type
Browse files Browse the repository at this point in the history
  • Loading branch information
brendangregg committed Sep 2, 2018
1 parent 93e4811 commit c1e7b05
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 2 deletions.
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,8 @@ Attach script to hardware events (PMCs), executing once every provided count or
`hardware:cache-references:1000000`
`hardware:cache-references:`

### timers
Run the script at specified time intervals:
### profile
Run the script on all CPUs at specified time intervals:

`profile:hz:99 { ... }`

Expand All @@ -180,6 +180,13 @@ Run the script at specified time intervals:

`profile:us:1500 { ... }`

### interval
Run the script once per interval, for printing interval output:

`interval:s:1 { ... }`

`interval:ms:20 { ... }`

### Multiple attachment points
A single probe can be attached to multiple events:

Expand Down
9 changes: 9 additions & 0 deletions src/ast/semantic_analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,15 @@ void SemanticAnalyser::visit(AttachPoint &ap)
else if (ap.freq <= 0)
err_ << "profile frequency should be a positive integer" << std::endl;
}
else if (ap.provider == "interval") {
if (ap.target == "")
err_ << "interval probe must have unit of time" << std::endl;
else if (ap.target != "ms" &&
ap.target != "s")
err_ << ap.target << " is not an accepted unit of time" << std::endl;
if (ap.func != "")
err_ << "interval probe must have an integer frequency" << std::endl;
}
else if (ap.provider == "software") {
if (ap.target == "")
err_ << "software probe must have a software event name" << std::endl;
Expand Down
36 changes: 36 additions & 0 deletions src/attached_probe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ bpf_prog_type progtype(ProbeType t)
case ProbeType::uretprobe: return BPF_PROG_TYPE_KPROBE; break;
case ProbeType::tracepoint: return BPF_PROG_TYPE_TRACEPOINT; break;
case ProbeType::profile: return BPF_PROG_TYPE_PERF_EVENT; break;
case ProbeType::interval: return BPF_PROG_TYPE_PERF_EVENT; break;
case ProbeType::software: return BPF_PROG_TYPE_PERF_EVENT; break;
case ProbeType::hardware: return BPF_PROG_TYPE_PERF_EVENT; break;
default: abort();
Expand Down Expand Up @@ -67,6 +68,9 @@ AttachedProbe::AttachedProbe(Probe &probe, std::tuple<uint8_t *, uintptr_t> func
case ProbeType::profile:
attach_profile();
break;
case ProbeType::interval:
attach_interval();
break;
case ProbeType::software:
attach_software();
break;
Expand Down Expand Up @@ -105,6 +109,7 @@ AttachedProbe::~AttachedProbe()
err = bpf_detach_tracepoint(probe_.path.c_str(), eventname().c_str());
break;
case ProbeType::profile:
case ProbeType::interval:
case ProbeType::software:
case ProbeType::hardware:
break;
Expand Down Expand Up @@ -327,6 +332,37 @@ void AttachedProbe::attach_profile()
}
}

void AttachedProbe::attach_interval()
{
int pid = -1;
int group_fd = -1;
int cpu = 0;

uint64_t period, freq;
if (probe_.path == "s")
{
period = probe_.freq * 1e9;
freq = 0;
}
else if (probe_.path == "ms")
{
period = probe_.freq * 1e6;
freq = 0;
}
else
{
abort();
}

int perf_event_fd = bpf_attach_perf_event(progfd_, PERF_TYPE_SOFTWARE,
PERF_COUNT_SW_CPU_CLOCK, period, freq, pid, cpu, group_fd);

if (perf_event_fd < 0)
throw std::runtime_error("Error attaching probe: " + probe_.name);

perf_event_fds_.push_back(perf_event_fd);
}

void AttachedProbe::attach_software()
{
int pid = -1;
Expand Down
1 change: 1 addition & 0 deletions src/attached_probe.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class AttachedProbe
void attach_uprobe();
void attach_tracepoint();
void attach_profile();
void attach_interval();
void attach_software();
void attach_hardware();

Expand Down
2 changes: 2 additions & 0 deletions src/types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ ProbeType probetype(const std::string &type)
return ProbeType::tracepoint;
else if (type == "profile")
return ProbeType::profile;
else if (type == "interval")
return ProbeType::interval;
else if (type == "software")
return ProbeType::software;
else if (type == "hardware")
Expand Down
1 change: 1 addition & 0 deletions src/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ enum class ProbeType
uretprobe,
tracepoint,
profile,
interval,
software,
hardware,
};
Expand Down
24 changes: 24 additions & 0 deletions tests/bpftrace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ void check_profile(Probe &p, const std::string &unit, int freq, const std::strin
EXPECT_EQ("profile:" + unit + ":" + std::to_string(freq), p.name);
}

void check_interval(Probe &p, const std::string &unit, int freq, const std::string &prog_name)
{
EXPECT_EQ(ProbeType::interval, p.type);
EXPECT_EQ(freq, p.freq);
EXPECT_EQ(prog_name, p.prog_name);
EXPECT_EQ("interval:" + unit + ":" + std::to_string(freq), p.name);
}

void check_software(Probe &p, const std::string &unit, int freq, const std::string &prog_name)
{
EXPECT_EQ(ProbeType::software, p.type);
Expand Down Expand Up @@ -325,6 +333,22 @@ TEST(bpftrace, add_probes_profile)
check_profile(bpftrace.get_probes().at(0), "ms", 997, probe_prog_name);
}

TEST(bpftrace, add_probes_interval)
{
ast::AttachPoint a("interval", "s", 1);
ast::AttachPointList attach_points = { &a };
ast::Probe probe(&attach_points, nullptr, nullptr);

StrictMock<MockBPFtrace> bpftrace;

EXPECT_EQ(0, bpftrace.add_probe(probe));
EXPECT_EQ(1, bpftrace.get_probes().size());
EXPECT_EQ(0, bpftrace.get_special_probes().size());

std::string probe_prog_name = "interval:s:1";
check_interval(bpftrace.get_probes().at(0), "s", 1, probe_prog_name);
}

TEST(bpftrace, add_probes_software)
{
ast::AttachPoint a("software", "faults", 1000);
Expand Down
8 changes: 8 additions & 0 deletions tests/parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,14 @@ TEST(Parser, profile_probe)
" int: 1\n");
}

TEST(Parser, interval_probe)
{
test("interval:s:1 { 1 }",
"Program\n"
" interval:s:1\n"
" int: 1\n");
}

TEST(Parser, software_probe)
{
test("software:faults:1000 { 1 }",
Expand Down

0 comments on commit c1e7b05

Please sign in to comment.