Skip to content

Commit 3099505

Browse files
Revert "[llvm-exegesis] Add ability to assign perf counters to specific PID"
Revert "[llvm-exegesis] Introduce Subprocess Executor Mode" This reverts commit 5e9173c. This reverts commit 4d618b5. Reverting the PID commit as it is currently breaking MinGW builds and the way I'm checking for the presence of pid_t needs to be fixed and I need to do some testing. The subprocess executor mode patch is a dependent patch so also needs to be reverted and also needs some work as it is currently failing tests where libpfm is installed and the kernel version is less than 5.6.
1 parent 53a7db4 commit 3099505

File tree

11 files changed

+17
-251
lines changed

11 files changed

+17
-251
lines changed

llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s

Lines changed: 0 additions & 9 deletions
This file was deleted.

llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s

Lines changed: 0 additions & 8 deletions
This file was deleted.

llvm/test/tools/llvm-exegesis/X86/latency/subprocess.s

Lines changed: 0 additions & 11 deletions
This file was deleted.

llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp

Lines changed: 0 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,6 @@
2525
#include "llvm/Support/FileSystem.h"
2626
#include "llvm/Support/MemoryBuffer.h"
2727
#include "llvm/Support/Program.h"
28-
#include "llvm/Support/Signals.h"
29-
30-
#ifdef __linux__
31-
#ifdef HAVE_LIBPFM
32-
#include <perfmon/perf_event.h>
33-
#endif
34-
#include <sys/mman.h>
35-
#include <sys/ptrace.h>
36-
#include <sys/syscall.h>
37-
#include <sys/wait.h>
38-
#include <unistd.h>
39-
#endif // __linux__
4028

4129
namespace llvm {
4230
namespace exegesis {
@@ -141,182 +129,6 @@ class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
141129
const ExecutableFunction Function;
142130
BenchmarkRunner::ScratchSpace *const Scratch;
143131
};
144-
145-
#ifdef __linux__
146-
// The following class implements a function executor that executes the
147-
// benchmark code within a subprocess rather than within the main llvm-exegesis
148-
// process. This allows for much more control over the execution context of the
149-
// snippet, particularly with regard to memory. This class performs all the
150-
// necessary functions to create the subprocess, execute the snippet in the
151-
// subprocess, and report results/handle errors.
152-
class SubProcessFunctionExecutorImpl
153-
: public BenchmarkRunner::FunctionExecutor {
154-
public:
155-
SubProcessFunctionExecutorImpl(const LLVMState &State,
156-
object::OwningBinary<object::ObjectFile> Obj,
157-
const BenchmarkKey &Key)
158-
: State(State), Function(State.createTargetMachine(), std::move(Obj)),
159-
Key(Key) {}
160-
161-
private:
162-
enum ChildProcessExitCodeE {
163-
CounterFDReadFailed = 1,
164-
TranslatingCounterFDFailed
165-
};
166-
167-
StringRef childProcessExitCodeToString(int ExitCode) const {
168-
switch (ExitCode) {
169-
case ChildProcessExitCodeE::CounterFDReadFailed:
170-
return "Counter file descriptor read failed";
171-
case ChildProcessExitCodeE::TranslatingCounterFDFailed:
172-
return "Translating counter file descriptor into a file descriptor in "
173-
"the child process failed. This might be due running an older "
174-
"Linux kernel that doesn't support the pidfd_getfd system call "
175-
"(anything before Linux 5.6).";
176-
default:
177-
return "Child process returned with unknown exit code";
178-
}
179-
}
180-
181-
Error createSubProcessAndRunBenchmark(
182-
StringRef CounterName, SmallVectorImpl<int64_t> &CounterValues) const {
183-
int PipeFiles[2];
184-
int PipeSuccessOrErr = pipe(PipeFiles);
185-
if (PipeSuccessOrErr != 0) {
186-
return make_error<Failure>(
187-
"Failed to create a pipe for interprocess communication between "
188-
"llvm-exegesis and the benchmarking subprocess");
189-
}
190-
191-
pid_t ParentOrChildPID = fork();
192-
if (ParentOrChildPID == 0) {
193-
// We are in the child process, close the write end of the pipe
194-
close(PipeFiles[1]);
195-
// Unregister handlers, signal handling is now handled through ptrace in
196-
// the host process
197-
llvm::sys::unregisterHandlers();
198-
prepareAndRunBenchmark(PipeFiles[0], Key);
199-
// The child process terminates in the above function, so we should never
200-
// get to this point.
201-
llvm_unreachable("Child process didn't exit when expected.");
202-
}
203-
204-
const ExegesisTarget &ET = State.getExegesisTarget();
205-
auto CounterOrError =
206-
ET.createCounter(CounterName, State, ParentOrChildPID);
207-
208-
if (!CounterOrError)
209-
return CounterOrError.takeError();
210-
211-
pfm::Counter *Counter = CounterOrError.get().get();
212-
213-
close(PipeFiles[0]);
214-
215-
int CounterFileDescriptor = Counter->getFileDescriptor();
216-
ssize_t BytesWritten =
217-
write(PipeFiles[1], &CounterFileDescriptor, sizeof(int));
218-
219-
if (BytesWritten != sizeof(int))
220-
return make_error<Failure>("Writing peformance counter file descriptor "
221-
"to child process failed: " +
222-
Twine(strerror(errno)));
223-
224-
if (ptrace(PTRACE_SEIZE, ParentOrChildPID, NULL, NULL) != 0)
225-
return make_error<Failure>("Failed to seize the child process: " +
226-
Twine(strerror(errno)));
227-
228-
int ChildStatus;
229-
if (wait(&ChildStatus) == -1) {
230-
return make_error<Failure>(
231-
"Waiting for the child process to complete failed: " +
232-
Twine(strerror(errno)));
233-
}
234-
235-
if (WIFEXITED(ChildStatus)) {
236-
int ChildExitCode = WEXITSTATUS(ChildStatus);
237-
if (ChildExitCode == 0) {
238-
// The child exited succesfully, read counter values and return
239-
// success
240-
CounterValues[0] = Counter->read();
241-
return Error::success();
242-
}
243-
// The child exited, but not successfully
244-
return make_error<SnippetCrash>(
245-
"Child benchmarking process exited with non-zero exit code: " +
246-
childProcessExitCodeToString(ChildExitCode));
247-
}
248-
249-
// An error was encountered running the snippet, process it
250-
siginfo_t ChildSignalInfo;
251-
if (ptrace(PTRACE_GETSIGINFO, ParentOrChildPID, NULL, &ChildSignalInfo) ==
252-
-1) {
253-
return make_error<Failure>("Getting signal info from the child failed: " +
254-
Twine(strerror(errno)));
255-
}
256-
257-
return make_error<SnippetCrash>(
258-
"The benchmarking subprocess sent unexpected signal: " +
259-
Twine(strsignal(ChildSignalInfo.si_signo)));
260-
}
261-
262-
[[noreturn]] void prepareAndRunBenchmark(int Pipe,
263-
const BenchmarkKey &Key) const {
264-
// The following occurs within the benchmarking subprocess
265-
266-
int ParentCounterFileDescriptor = -1;
267-
ssize_t BytesRead = read(Pipe, &ParentCounterFileDescriptor, sizeof(int));
268-
269-
if (BytesRead != sizeof(int)) {
270-
exit(ChildProcessExitCodeE::CounterFDReadFailed);
271-
}
272-
273-
// Make sure the following two syscalls are defined on the platform that
274-
// we're building on as they were introduced to the kernel fairly recently
275-
// (v5.6 for the second one).
276-
#if defined SYS_pidfd_open && defined SYS_pidfd_getfd
277-
pid_t ParentPID = getppid();
278-
279-
int ParentPIDFD = syscall(SYS_pidfd_open, ParentPID, 0);
280-
int CounterFileDescriptor =
281-
syscall(SYS_pidfd_getfd, ParentPIDFD, ParentCounterFileDescriptor, 0);
282-
#else
283-
int CounterFileDescriptor = 0;
284-
exit(ChildProcessExitCodeE::TranslatingCounterFDFailed);
285-
#endif
286-
287-
if (CounterFileDescriptor == -1) {
288-
exit(ChildProcessExitCodeE::TranslatingCounterFDFailed);
289-
}
290-
291-
#ifdef HAVE_LIBPFM
292-
ioctl(CounterFileDescriptor, PERF_EVENT_IOC_RESET);
293-
#endif
294-
this->Function(nullptr);
295-
#ifdef HAVE_LIBPFM
296-
ioctl(CounterFileDescriptor, PERF_EVENT_IOC_DISABLE);
297-
#endif
298-
299-
exit(0);
300-
}
301-
302-
Expected<llvm::SmallVector<int64_t, 4>>
303-
runWithCounter(StringRef CounterName) const override {
304-
SmallVector<int64_t, 4> Value(1, 0);
305-
Error PossibleBenchmarkError =
306-
createSubProcessAndRunBenchmark(CounterName, Value);
307-
308-
if (PossibleBenchmarkError) {
309-
return std::move(PossibleBenchmarkError);
310-
}
311-
312-
return Value;
313-
}
314-
315-
const LLVMState &State;
316-
const ExecutableFunction Function;
317-
const BenchmarkKey &Key;
318-
};
319-
#endif // __linux__
320132
} // namespace
321133

322134
Expected<SmallString<0>> BenchmarkRunner::assembleSnippet(
@@ -389,14 +201,6 @@ BenchmarkRunner::createFunctionExecutor(
389201
case ExecutionModeE::InProcess:
390202
return std::make_unique<InProcessFunctionExecutorImpl>(
391203
State, std::move(ObjectFile), Scratch.get());
392-
case ExecutionModeE::SubProcess:
393-
#ifdef __linux__
394-
return std::make_unique<SubProcessFunctionExecutorImpl>(
395-
State, std::move(ObjectFile), Key);
396-
#else
397-
return make_error<Failure>(
398-
"The subprocess execution mode is only supported on Linux");
399-
#endif
400204
}
401205
llvm_unreachable("ExecutionMode is outside expected range");
402206
}

llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace exegesis {
3434
// Common code for all benchmark modes.
3535
class BenchmarkRunner {
3636
public:
37-
enum ExecutionModeE { InProcess, SubProcess };
37+
enum ExecutionModeE { InProcess };
3838

3939
explicit BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode,
4040
BenchmarkPhaseSelectorE BenchmarkPhaseSelector,

llvm/tools/llvm-exegesis/lib/PerfHelper.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,21 @@ StringRef PerfEvent::getPfmEventString() const {
107107
return FullQualifiedEventString;
108108
}
109109

110-
Counter::Counter(PerfEvent &&E, pid_t ProcessID) : Event(std::move(E)) {
110+
Counter::Counter(PerfEvent &&E) : Event(std::move(E)){
111111
assert(Event.valid());
112112
IsDummyEvent = Event.name() == PerfEvent::DummyEventString;
113113
if (!IsDummyEvent)
114-
initRealEvent(E, ProcessID);
114+
initRealEvent(E);
115115
}
116116

117117
#ifdef HAVE_LIBPFM
118-
void Counter::initRealEvent(const PerfEvent &E, pid_t ProcessID) {
118+
void Counter::initRealEvent(const PerfEvent &E) {
119+
const pid_t Pid = 0; // measure current process/thread.
119120
const int Cpu = -1; // measure any processor.
120121
const int GroupFd = -1; // no grouping of counters.
121122
const uint32_t Flags = 0;
122123
perf_event_attr AttrCopy = *Event.attribute();
123-
FileDescriptor = perf_event_open(&AttrCopy, ProcessID, Cpu, GroupFd, Flags);
124+
FileDescriptor = perf_event_open(&AttrCopy, Pid, Cpu, GroupFd, Flags);
124125
if (FileDescriptor == -1) {
125126
errs() << "Unable to open event. ERRNO: " << strerror(errno)
126127
<< ". Make sure your kernel allows user "
@@ -179,7 +180,7 @@ Counter::readOrError(StringRef /*unused*/) const {
179180
int Counter::numValues() const { return 1; }
180181
#else
181182

182-
void Counter::initRealEvent(const PerfEvent &, pid_t ProcessID) {}
183+
void Counter::initRealEvent(const PerfEvent &) {}
183184

184185
Counter::~Counter() = default;
185186

llvm/tools/llvm-exegesis/lib/PerfHelper.h

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@
2323
#include <functional>
2424
#include <memory>
2525

26-
#ifndef HAVE_LIBPFM
27-
typedef int pid_t;
28-
#endif // HAVE_LIBPFM
29-
3026
struct perf_event_attr;
3127

3228
namespace llvm {
@@ -80,7 +76,7 @@ class PerfEvent {
8076
class Counter {
8177
public:
8278
// event: the PerfEvent to measure.
83-
explicit Counter(PerfEvent &&event, pid_t ProcessID = 0);
79+
explicit Counter(PerfEvent &&event);
8480

8581
Counter(const Counter &) = delete;
8682
Counter(Counter &&other) = default;
@@ -107,15 +103,15 @@ class Counter {
107103

108104
virtual int numValues() const;
109105

110-
int getFileDescriptor() const { return FileDescriptor; }
111-
112106
protected:
113107
PerfEvent Event;
108+
#ifdef HAVE_LIBPFM
114109
int FileDescriptor = -1;
110+
#endif
115111
bool IsDummyEvent;
116112

117113
private:
118-
void initRealEvent(const PerfEvent &E, pid_t ProcessID);
114+
void initRealEvent(const PerfEvent &E);
119115
};
120116

121117
} // namespace pfm

llvm/tools/llvm-exegesis/lib/Target.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,15 @@ const ExegesisTarget *ExegesisTarget::lookup(Triple TT) {
3535
}
3636

3737
Expected<std::unique_ptr<pfm::Counter>>
38-
ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &,
39-
const pid_t ProcessID) const {
38+
ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &) const {
4039
pfm::PerfEvent Event(CounterName);
4140
if (!Event.valid())
4241
return llvm::make_error<Failure>(
4342
llvm::Twine("Unable to create counter with name '")
4443
.concat(CounterName)
4544
.concat("'"));
4645

47-
return std::make_unique<pfm::Counter>(std::move(Event), ProcessID);
46+
return std::make_unique<pfm::Counter>(std::move(Event));
4847
}
4948

5049
void ExegesisTarget::registerTarget(ExegesisTarget *Target) {

llvm/tools/llvm-exegesis/lib/Target.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ class ExegesisTarget {
7575

7676
// Targets can use this to create target-specific perf counters.
7777
virtual Expected<std::unique_ptr<pfm::Counter>>
78-
createCounter(StringRef CounterName, const LLVMState &State,
79-
const pid_t ProcessID = 0) const;
78+
createCounter(StringRef CounterName, const LLVMState &State) const;
8079

8180
// Targets can use this to add target-specific passes in assembleToStream();
8281
virtual void addTargetSpecificPasses(PassManagerBase &PM) const {}

llvm/tools/llvm-exegesis/lib/X86/Target.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -665,8 +665,7 @@ class ExegesisX86Target : public ExegesisTarget {
665665
ExegesisX86Target() : ExegesisTarget(X86CpuPfmCounters) {}
666666

667667
Expected<std::unique_ptr<pfm::Counter>>
668-
createCounter(StringRef CounterName, const LLVMState &State,
669-
const pid_t ProcessID) const override {
668+
createCounter(StringRef CounterName, const LLVMState &State) const override {
670669
// If LbrSamplingPeriod was provided, then ignore the
671670
// CounterName because we only have one for LBR.
672671
if (LbrSamplingPeriod > 0) {
@@ -683,7 +682,7 @@ class ExegesisX86Target : public ExegesisTarget {
683682
llvm::errc::invalid_argument);
684683
#endif
685684
}
686-
return ExegesisTarget::createCounter(CounterName, State, ProcessID);
685+
return ExegesisTarget::createCounter(CounterName, State);
687686
}
688687

689688
private:

llvm/tools/llvm-exegesis/llvm-exegesis.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,7 @@ static cl::opt<BenchmarkRunner::ExecutionModeE> ExecutionMode(
254254
cl::cat(BenchmarkOptions),
255255
cl::values(clEnumValN(BenchmarkRunner::ExecutionModeE::InProcess,
256256
"inprocess",
257-
"Executes the snippets within the same process"),
258-
clEnumValN(BenchmarkRunner::ExecutionModeE::SubProcess,
259-
"subprocess",
260-
"Spawns a subprocess for each snippet execution, "
261-
"allows for the use of memory annotations")),
257+
"Executes the snippets within the same process")),
262258
cl::init(BenchmarkRunner::ExecutionModeE::InProcess));
263259

264260
static ExitOnError ExitOnErr("llvm-exegesis error: ");

0 commit comments

Comments
 (0)