From 08aeb7c35ddbb8113fa95c4ffee4fc9493259ceb Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Wed, 21 Jun 2023 02:28:35 +0000 Subject: [PATCH] Revert "[llvm-exegesis] Introduce Subprocess Executor Mode" This reverts commit 0d4ef4ff01addbb40b9122a00d6b2f23104cbb3b. This was causing build failures on certain platforms when built with -Werror due to unused variable warnings in addition to causing build failures on Linux systems with older kernel versions as kernels prior to v5.15 don't support sys_pidfd_getpid. Reverting as I need to setup a system to properly test the rest of the patches in this series. Also reverts 8c6668fa42dba59ddc286ba256d71c1b9c5228b8 which fixed the first issue so that the patch can actually be reverted. --- .../X86/latency/subprocess-abnormal-exit-code.s | 9 - .../X86/latency/subprocess-segfault.s | 8 - .../tools/llvm-exegesis/X86/latency/subprocess.s | 11 -- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp | 192 --------------------- llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h | 2 +- llvm/tools/llvm-exegesis/llvm-exegesis.cpp | 6 +- 6 files changed, 2 insertions(+), 226 deletions(-) delete mode 100644 llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s delete mode 100644 llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s delete mode 100644 llvm/test/tools/llvm-exegesis/X86/latency/subprocess.s diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s deleted file mode 100644 index 9e28982..0000000 --- a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-abnormal-exit-code.s +++ /dev/null @@ -1,9 +0,0 @@ -# REQUIRES: exegesis-can-execute-x86_64, exegesis-can-measure-latency, x86_64-linux - -# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s - -# CHECK: error: 'Child benchmarking process exited with non-zero exit code: Child process returned with unknown exit code' - -movl $60, %eax -movl $127, %edi -syscall diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s deleted file mode 100644 index 56a5c18..0000000 --- a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess-segfault.s +++ /dev/null @@ -1,8 +0,0 @@ -# REQUIRES: exegesis-can-execute-x86_64, exegesis-can-measure-latency, x86_64-linux - -# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s - -# CHECK: error: 'The benchmarking subprocess sent unexpected signal: Segmentation fault' - -# LLVM-EXEGESIS-DEFREG RBX 0 -movq (%rbx), %rax diff --git a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess.s b/llvm/test/tools/llvm-exegesis/X86/latency/subprocess.s deleted file mode 100644 index a8cfe9f..0000000 --- a/llvm/test/tools/llvm-exegesis/X86/latency/subprocess.s +++ /dev/null @@ -1,11 +0,0 @@ -# REQUIRES: exegesis-can-execute-x86_64, exegesis-can-measure-latency, x86_64-linux - -# RUN: llvm-exegesis -mtriple=x86_64-unknown-unknown -mode=latency -snippets-file=%s -execution-mode=subprocess | FileCheck %s - -# CHECK: measurements: -# CHECK-NEXT: value: {{.*}}, per_snippet_value: {{.*}} - -# LLVM-EXEGESIS-DEFREG XMM1 42 -# LLVM-EXEGESIS-DEFREG XMM2 42 -# LLVM-EXEGESIS-DEFREG XMM3 42 -vhaddps %xmm2, %xmm2, %xmm3 diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp index 2b0a93a..09539e8 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp @@ -25,18 +25,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Program.h" -#include "llvm/Support/Signals.h" - -#ifdef __linux__ -#ifdef HAVE_LIBPFM -#include -#endif -#include -#include -#include -#include -#include -#endif // __linux__ namespace llvm { namespace exegesis { @@ -141,178 +129,6 @@ private: const ExecutableFunction Function; BenchmarkRunner::ScratchSpace *const Scratch; }; - -#ifdef __linux__ -// The following class implements a function executor that executes the -// benchmark code within a subprocess rather than within the main llvm-exegesis -// process. This allows for much more control over the execution context of the -// snippet, particularly with regard to memory. This class performs all the -// necessary functions to create the subprocess, execute the snippet in the -// subprocess, and report results/handle errors. -class SubProcessFunctionExecutorImpl - : public BenchmarkRunner::FunctionExecutor { -public: - SubProcessFunctionExecutorImpl(const LLVMState &State, - object::OwningBinary Obj, - const BenchmarkKey &Key) - : State(State), Function(State.createTargetMachine(), std::move(Obj)), - Key(Key) {} - -private: - enum ChildProcessExitCodeE { - CounterFDReadFailed = 1, - TranslatingCounterFDFailed - }; - - StringRef childProcessExitCodeToString(int ExitCode) const { - switch (ExitCode) { - case ChildProcessExitCodeE::CounterFDReadFailed: - return "Counter file descriptor read failed"; - case ChildProcessExitCodeE::TranslatingCounterFDFailed: - return "Translating counter file descriptor into a file descriptor in " - "the child process failed. This might be due running an older " - "Linux kernel that doesn't support the pidfd_getfd system call " - "(anything before Linux 5.6)."; - default: - return "Child process returned with unknown exit code"; - } - } - - Error createSubProcessAndRunBenchmark( - StringRef CounterName, SmallVectorImpl &CounterValues) const { - int PipeFiles[2]; - int PipeSuccessOrErr = pipe(PipeFiles); - if (PipeSuccessOrErr != 0) { - return make_error( - "Failed to create a pipe for interprocess communication between " - "llvm-exegesis and the benchmarking subprocess"); - } - - pid_t ParentOrChildPID = fork(); - if (ParentOrChildPID == 0) { - // We are in the child process, close the write end of the pipe - close(PipeFiles[1]); - // Unregister handlers, signal handling is now handled through ptrace in - // the host process - llvm::sys::unregisterHandlers(); - prepareAndRunBenchmark(PipeFiles[0], Key); - // The child process terminates in the above function, so we should never - // get to this point. - llvm_unreachable("Child process didn't exit when expected."); - } - - const ExegesisTarget &ET = State.getExegesisTarget(); - auto CounterOrError = - ET.createCounter(CounterName, State, ParentOrChildPID); - - if (!CounterOrError) - return CounterOrError.takeError(); - - pfm::Counter *Counter = CounterOrError.get().get(); - - close(PipeFiles[0]); - - int CounterFileDescriptor = Counter->getFileDescriptor(); - ssize_t BytesWritten = - write(PipeFiles[1], &CounterFileDescriptor, sizeof(int)); - - if (BytesWritten != sizeof(int)) - return make_error("Writing peformance counter file descriptor " - "to child process failed: " + - Twine(strerror(errno))); - - if (ptrace(PTRACE_SEIZE, ParentOrChildPID, NULL, NULL) != 0) - return make_error("Failed to seize the child process: " + - Twine(strerror(errno))); - - int ChildStatus; - if (wait(&ChildStatus) == -1) { - return make_error( - "Waiting for the child process to complete failed: " + - Twine(strerror(errno))); - } - - if (WIFEXITED(ChildStatus)) { - int ChildExitCode = WEXITSTATUS(ChildStatus); - if (ChildExitCode == 0) { - // The child exited succesfully, read counter values and return - // success - CounterValues[0] = Counter->read(); - return Error::success(); - } - // The child exited, but not successfully - return make_error( - "Child benchmarking process exited with non-zero exit code: " + - childProcessExitCodeToString(ChildExitCode)); - } - - // An error was encountered running the snippet, process it - siginfo_t ChildSignalInfo; - if (ptrace(PTRACE_GETSIGINFO, ParentOrChildPID, NULL, &ChildSignalInfo) == - -1) { - return make_error("Getting signal info from the child failed: " + - Twine(strerror(errno))); - } - - return make_error( - "The benchmarking subprocess sent unexpected signal: " + - Twine(strsignal(ChildSignalInfo.si_signo))); - } - - [[noreturn]] void prepareAndRunBenchmark(int Pipe, - const BenchmarkKey &Key) const { - // The following occurs within the benchmarking subprocess - - int ParentCounterFileDescriptor = -1; - ssize_t BytesRead = read(Pipe, &ParentCounterFileDescriptor, sizeof(int)); - - if (BytesRead != sizeof(int)) { - exit(ChildProcessExitCodeE::CounterFDReadFailed); - } - -#ifdef SYS_pidfd_getfd - pid_t ParentPID = getppid(); - int ParentPIDFD = syscall(SYS_pidfd_open, ParentPID, 0); - int CounterFileDescriptor = - syscall(SYS_pidfd_getfd, ParentPIDFD, ParentCounterFileDescriptor, 0); -#else - int CounterFileDescriptor = 0; - exit(ChildProcessExitCodeE::TranslatingCounterFDFailed); -#endif - - if (CounterFileDescriptor == -1) { - exit(ChildProcessExitCodeE::TranslatingCounterFDFailed); - } - -#ifdef HAVE_LIBPFM - ioctl(CounterFileDescriptor, PERF_EVENT_IOC_RESET); -#endif - this->Function(nullptr); -#ifdef HAVE_LIBPFM - ioctl(CounterFileDescriptor, PERF_EVENT_IOC_DISABLE); -#endif - - exit(0); - } - - Expected> - runWithCounter(StringRef CounterName) const override { - SmallVector Value(1, 0); - Error PossibleBenchmarkError = - createSubProcessAndRunBenchmark(CounterName, Value); - - if (PossibleBenchmarkError) { - return std::move(PossibleBenchmarkError); - } - - return Value; - } - - const LLVMState &State; - const ExecutableFunction Function; - const BenchmarkKey &Key; -}; -#endif // __linux__ } // namespace Expected> BenchmarkRunner::assembleSnippet( @@ -385,14 +201,6 @@ BenchmarkRunner::createFunctionExecutor( case ExecutionModeE::InProcess: return std::make_unique( State, std::move(ObjectFile), Scratch.get()); - case ExecutionModeE::SubProcess: -#ifdef __linux__ - return std::make_unique( - State, std::move(ObjectFile), Key); -#else - return make_error( - "The subprocess execution mode is only supported on Linux"); -#endif } llvm_unreachable("ExecutionMode is outside expected range"); } diff --git a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h index 88559901..e5185b4 100644 --- a/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h +++ b/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h @@ -34,7 +34,7 @@ namespace exegesis { // Common code for all benchmark modes. class BenchmarkRunner { public: - enum ExecutionModeE { InProcess, SubProcess }; + enum ExecutionModeE { InProcess }; explicit BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode, BenchmarkPhaseSelectorE BenchmarkPhaseSelector, diff --git a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp index 82df07c..d890fbb 100644 --- a/llvm/tools/llvm-exegesis/llvm-exegesis.cpp +++ b/llvm/tools/llvm-exegesis/llvm-exegesis.cpp @@ -254,11 +254,7 @@ static cl::opt ExecutionMode( cl::cat(BenchmarkOptions), cl::values(clEnumValN(BenchmarkRunner::ExecutionModeE::InProcess, "inprocess", - "Executes the snippets within the same process"), - clEnumValN(BenchmarkRunner::ExecutionModeE::SubProcess, - "subprocess", - "Spawns a subprocess for each snippet execution, " - "allows for the use of memory annotations")), + "Executes the snippets within the same process")), cl::init(BenchmarkRunner::ExecutionModeE::InProcess)); static ExitOnError ExitOnErr("llvm-exegesis error: "); -- 2.7.4