Commit c1e7b05b authored by Brendan Gregg's avatar Brendan Gregg

add interval probe type

parent 93e4811a
......@@ -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 { ... }`
......@@ -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:
......
......@@ -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;
......
......@@ -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();
......@@ -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;
......@@ -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;
......@@ -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;
......
......@@ -27,6 +27,7 @@ private:
void attach_uprobe();
void attach_tracepoint();
void attach_profile();
void attach_interval();
void attach_software();
void attach_hardware();
......
......@@ -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")
......
......@@ -51,6 +51,7 @@ enum class ProbeType
uretprobe,
tracepoint,
profile,
interval,
software,
hardware,
};
......
......@@ -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);
......@@ -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);
......
......@@ -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 }",
......
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