Skip to content

Commit

Permalink
perform ucontext->pc variants testing in compile-time
Browse files Browse the repository at this point in the history
As part of cpu profiler we're extracting current PC (program counter)
of out signal's ucontext. Different OS and hardware combinations have
different ways for that. We had a list of variants that we tested at
compile time and populated PC_FROM_UCONTEXT macro into config.h. It
caused duplication and occasional mismatches between our autoconf and
cmake bits.

So this commit changes testing to be compile-time. We remove
complexity from build system and add some to C++ source.

We use SFINAE to find which of those variants compile (and we silently
assume that 'compiles' implies 'works'; this is what config-time
testing did too). Occasionally we'll face situations where several
variants compile. And we couldn't handle this case in pure C++. So we
have a small Ruby program that generates chain of inheritance among
SFINAE-specialized class templates. This handles prioritization among
variants.

List of ucontext->pc extraction variants is mostly same. We dropped
super-obsolete (circa Linux kernel 2.0) arm variant. And NetBSD case
is now improved. We now use their nice architecture-independent macro
instead of x86-specific access.
  • Loading branch information
alk committed Dec 2, 2023
1 parent 8edeea4 commit a9b734e
Show file tree
Hide file tree
Showing 11 changed files with 666 additions and 205 deletions.
14 changes: 3 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ include(GNUInstallDirs)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(DefineTargetVariables)
include(PCFromUContext)

define_target_variables()

Expand Down Expand Up @@ -191,6 +190,9 @@ check_include_file("grp.h" HAVE_GRP_H) # for heapchecker_unittest
check_include_file("pwd.h" HAVE_PWD_H) # for heapchecker_unittest
check_include_file("sys/resource.h" HAVE_SYS_RESOURCE_H) # for memalign_unittest.cc
check_include_file("sys/cdefs.h" HAVE_SYS_CDEFS_H) # Where glibc defines __THROW
check_include_file("ucontext.h" HAVE_UCONTEXT_H)
check_include_file("sys/ucontext.h" HAVE_SYS_UCONTEXT_H)
check_include_file("cygwin/signal.h" HAVE_CYGWIN_SIGNAL_H)

check_include_file("unistd.h" HAVE_UNISTD_H)
# We also need <ucontext.h>/<sys/ucontext.h>, but we get those from
Expand Down Expand Up @@ -220,16 +222,6 @@ if(NOT WIN32)
set(HAVE_MMAP 1)
endif()

# We want to access the "PC" (Program Counter) register from a struct
# ucontext. Every system has its own way of doing that. We try all the
# possibilities we know about. Note REG_PC should come first (REG_RIP
# is also defined on solaris, but does the wrong thing). But don't
# bother if we're not doing cpu-profiling.
# [*] means that we've not actually tested one of these systems
if (GPERFTOOLS_BUILD_CPU_PROFILER)
pc_from_ucontext(PC_FROM_UCONTEXT_DEF)
endif ()

# Some tests test the behavior of .so files, and only make sense for dynamic.
option(GPERFTOOLS_BUILD_STATIC "Enable Static" ON)

Expand Down
67 changes: 0 additions & 67 deletions cmake/PCFromUContext.cmake

This file was deleted.

3 changes: 0 additions & 3 deletions cmake/config.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -206,9 +206,6 @@
/* Define to the version of this package. */
#define PACKAGE_VERSION "@PROJECT_VERSION@"

/* How to access the PC from a struct ucontext */
#define PC_FROM_UCONTEXT @PC_FROM_UCONTEXT_DEF@

/* Always the empty-string on non-windows systems. On windows, should be
"__declspec(dllexport)". This way, when we compile the dll, we export our
functions/classes. It's safe to define this here because config.h is only
Expand Down
21 changes: 12 additions & 9 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,11 @@ AC_CHECK_HEADERS(grp.h) # for heapchecker_unittest
AC_CHECK_HEADERS(pwd.h) # for heapchecker_unittest
AC_CHECK_HEADERS(sys/resource.h) # for memalign_unittest.cc
AC_CHECK_HEADERS(sys/cdefs.h) # Where glibc defines __THROW
# We also need <ucontext.h>/<sys/ucontext.h>, but we get those from
# AC_PC_FROM_UCONTEXT, below.

AC_CHECK_HEADERS(sys/ucontext.h)
AC_CHECK_HEADERS(ucontext.h)
AC_CHECK_HEADERS(cygwin/signal.h) # ucontext on cywgin
AC_CHECK_HEADERS(asm/ptrace.h) # get ptrace macros, e.g. PT_NIP

# check for socketpair, some system, such as QNX, need link in an socket library to use it
AC_SEARCH_LIBS([socketpair], [socket])
Expand Down Expand Up @@ -305,14 +308,14 @@ case "$host" in
esac

# We want to access the "PC" (Program Counter) register from a struct
# ucontext. Every system has its own way of doing that. We try all the
# possibilities we know about. Note REG_PC should come first (REG_RIP
# is also defined on solaris, but does the wrong thing). But don't
# bother if we're not doing cpu-profiling.
# [*] means that we've not actually tested one of these systems
# ucontext. Every system has its own way of doing that. But in case
# we're dealing with unknown system, we have to check if GetPC
# actually works. But don't bother if we're not doing cpu-profiling.
if test "$enable_cpu_profiler" = yes; then
AC_PC_FROM_UCONTEXT(AC_MSG_WARN(Could not find the PC. Will not try to compile libprofiler...);
enable_cpu_profiler=no)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include "src/getpc.h"]], [GetPC({})])],
[],
[AC_MSG_WARN(Could not find the PC. Will not try to compile libprofiler...)
enable_cpu_profiler=no])
fi

# Some tests test the behavior of .so files, and only make sense for dynamic.
Expand Down
100 changes: 0 additions & 100 deletions m4/pc_from_ucontext.m4

This file was deleted.

0 comments on commit a9b734e

Please sign in to comment.