User API + reorganized lib folders (#30)
* User API + reorganized lib folders - omnitrace_user_start_trace - omnitrace_user_stop_trace - omnitrace_user_start_thread_trace - omnitrace_user_stop_thread_trace - omnitrace_user_push_region - omnitrace_user_pop_region * New OpenMP examples/tests * Fix to KokkosP * OMPT support - fixed omnitrace instrumenting reporting - common invoke improvements - component::user_region * exclude kmp_threadprivate_ * Separate omnitrace into multiple files * PTL and timemory submodule updates * Active guards + USE_OMPT guards in omnitrace-dl * Tweak transpose default iterations * omnitrace-precommit build target * Omnitrace exe restructuring pt 2 - Never instrument functions with less than 4 instructions - Never instrument ompt_start_tool or nanosleep - module_function serializes heuristics - removed hash stuff from omnitrace - removed instr_procedures lambda - WAITPID_DEBUG_MESSAGE * set_state, "_hidden" fix, CI exceptions, backtrace fix - set_state function - fixed "_hidden" from appearing in print macros using __FUNCTION__ - OMNITRACE_CI_THROW - more CI checks in library - fixed backtrace init value sample issue being ignored * Tweaks to OMPT tests * cmake-formatting * Removed debug output from backtrace processing * Fix warnings and verbosity * omnitrace-dl fix for libomp * omnitrace-avail fixes - remove second omnitrace_init_library call - fix -r option not working * Additional testing - source/bin/tests - tests for omnitrace-exe - tests for omnitrace-avail * cmake-format * Reduce runtime of openmp-lu * Update openmp-lu and tests timeout * openmp-lu and CI tweaks - decrease iterations - OMP_NUM_THREADS=2 - install clang and libomp-dev in linux-ci - fix data-files in linux-ci
Cette révision appartient à :
révisé par
GitHub
Parent
2acaa7aa9f
révision
d80752bc69
@@ -35,6 +35,23 @@ parse:
|
||||
PUBLIC: '*'
|
||||
PRIVATE: '*'
|
||||
INTERFACE: '*'
|
||||
omnitrace_add_bin_test:
|
||||
flags:
|
||||
- WILL_FAIL
|
||||
kwargs:
|
||||
NAME: '*'
|
||||
ARGS: '*'
|
||||
LABELS: '*'
|
||||
TARGET: '*'
|
||||
DEPENDS: '*'
|
||||
COMMAND: '*'
|
||||
TIMEOUT: '*'
|
||||
PROPERTIES: '*'
|
||||
ENVIRONMENT: '*'
|
||||
WORKING_DIRECTORY: '*'
|
||||
PASS_REGULAR_EXPRESSION: '*'
|
||||
FAIL_REGULAR_EXPRESSION: '*'
|
||||
SKIP_REGULAR_EXPRESSION: '*'
|
||||
override_spec: {}
|
||||
vartags: []
|
||||
proptags: []
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libtbb-dev libboost-{atomic,system,thread,date-time,filesystem,timer}-dev ${{ matrix.compiler }} ${{ matrix.mpi }} &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libtbb-dev libboost-{atomic,system,thread,date-time,filesystem,timer}-dev clang libomp-dev ${{ matrix.compiler }} ${{ matrix.mpi }} &&
|
||||
python3 -m pip install --upgrade pip &&
|
||||
python3 -m pip install 'cmake==3.16.3'
|
||||
|
||||
@@ -107,7 +107,7 @@ jobs:
|
||||
with:
|
||||
name: data-files
|
||||
path: |
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
|
||||
|
||||
ubuntu-bionic:
|
||||
runs-on: ubuntu-18.04
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
with:
|
||||
name: data-files
|
||||
path: |
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
|
||||
|
||||
ubuntu-focal-external:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -217,7 +217,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev ${{ matrix.compiler }} &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev clang libomp-dev ${{ matrix.compiler }} &&
|
||||
sudo python3 -m pip install --upgrade pip &&
|
||||
python3 -m pip install 'cmake==3.16.3'
|
||||
|
||||
@@ -321,7 +321,7 @@ jobs:
|
||||
with:
|
||||
name: data-files
|
||||
path: |
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
|
||||
|
||||
ubuntu-focal-dyninst-package:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -336,7 +336,7 @@ jobs:
|
||||
timeout-minutes: 5
|
||||
run:
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip ${{ matrix.compiler }} &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip clang libomp-dev ${{ matrix.compiler }} &&
|
||||
sudo python3 -m pip install --upgrade pip &&
|
||||
python3 -m pip install 'cmake==3.16.3'
|
||||
|
||||
@@ -432,7 +432,7 @@ jobs:
|
||||
with:
|
||||
name: data-files
|
||||
path: |
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/*.txt
|
||||
${{ github.workspace }}/build/omnitrace-tests-output/**/*.txt
|
||||
|
||||
ubuntu-focal-external-rocm:
|
||||
runs-on: ubuntu-20.04
|
||||
@@ -454,7 +454,7 @@ jobs:
|
||||
sudo wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | sudo apt-key add - &&
|
||||
echo "deb [arch=amd64] https://repo.radeon.com/rocm/apt/${{ matrix.rocm_version }}/ ubuntu main" | sudo tee /etc/apt/sources.list.d/rocm.list &&
|
||||
sudo apt-get update &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev ${{ matrix.compiler }} libudev-dev libnuma-dev rocm-dev rocm-utils roctracer-dev rocprofiler-dev hip-base hsa-amd-aqlprofile hsa-rocr-dev hsakmt-roct-dev ${{ matrix.mpi }} libpapi-dev &&
|
||||
sudo apt-get install -y build-essential m4 autoconf libtool python3-pip libboost-{atomic,system,thread,date-time,filesystem,timer}-dev libtbb-dev libiberty-dev clang libomp-dev ${{ matrix.compiler }} libudev-dev libnuma-dev rocm-dev rocm-utils roctracer-dev rocprofiler-dev hip-base hsa-amd-aqlprofile hsa-rocr-dev hsakmt-roct-dev ${{ matrix.mpi }} libpapi-dev &&
|
||||
sudo python3 -m pip install --upgrade pip &&
|
||||
python3 -m pip install 'cmake==3.16.3'
|
||||
|
||||
|
||||
+14
-4
@@ -74,7 +74,9 @@ omnitrace_add_option(
|
||||
${OMNITRACE_USE_HIP})
|
||||
omnitrace_add_option(OMNITRACE_USE_MPI_HEADERS
|
||||
"Enable wrapping MPI functions w/o enabling MPI dependency" OFF)
|
||||
omnitrace_add_option(OMNITRACE_USE_OMPT "Enable OpenMP tools support" OFF)
|
||||
omnitrace_add_option(OMNITRACE_BUILD_DYNINST "Build dyninst from submodule" OFF)
|
||||
omnitrace_add_option(OMNITRACE_BUILD_EXAMPLES "Enable building the examples" OFF)
|
||||
omnitrace_add_option(OMNITRACE_BUILD_TESTING "Enable building the testing suite" OFF)
|
||||
omnitrace_add_option(OMNITRACE_CUSTOM_DATA_SOURCE "Enable custom data source" OFF)
|
||||
omnitrace_add_option(OMNITRACE_BUILD_HIDDEN_VISIBILITY
|
||||
@@ -98,6 +100,12 @@ if(NOT OMNITRACE_USE_HIP)
|
||||
CACHE BOOL "Disabled via OMNITRACE_USE_HIP=OFF" FORCE)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_BUILD_TESTING)
|
||||
set(OMNITRACE_BUILD_EXAMPLES
|
||||
ON
|
||||
CACHE BOOL "Enable building the examples" FORCE)
|
||||
endif()
|
||||
|
||||
include(ProcessorCount)
|
||||
processorcount(OMNITRACE_PROCESSOR_COUNT)
|
||||
math(EXPR OMNITRACE_THREAD_COUNT "16 * ${OMNITRACE_PROCESSOR_COUNT}")
|
||||
@@ -151,6 +159,11 @@ if(OMNITRACE_BUILD_HIDDEN_VISIBILITY)
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_BUILD_TESTING)
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# library and executables
|
||||
@@ -193,7 +206,7 @@ if(OMNITRACE_BUILD_LTO)
|
||||
omnitrace_restore_variables(LTO VARIABLES CMAKE_INTERPROCEDURAL_OPTIMIZATION)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_BUILD_TESTING)
|
||||
if(OMNITRACE_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
|
||||
@@ -204,9 +217,6 @@ endif()
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
if(OMNITRACE_BUILD_TESTING)
|
||||
include(CTest)
|
||||
enable_testing()
|
||||
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
|
||||
@@ -40,25 +40,45 @@ endmacro()
|
||||
find_program(OMNITRACE_CLANG_FORMAT_EXE NAMES clang-format-11 clang-format-mp-11
|
||||
clang-format)
|
||||
|
||||
find_program(OMNITRACE_CMAKE_FORMAT_EXE NAMES cmake-format)
|
||||
|
||||
if(OMNITRACE_CLANG_FORMAT_EXE)
|
||||
file(GLOB_RECURSE sources ${PROJECT_SOURCE_DIR}/source/*.cpp)
|
||||
file(GLOB_RECURSE headers ${PROJECT_SOURCE_DIR}/source/*.hpp
|
||||
${PROJECT_SOURCE_DIR}/source/*.hpp.in)
|
||||
${PROJECT_SOURCE_DIR}/source/*.hpp.in ${PROJECT_SOURCE_DIR}/source/*.h
|
||||
${PROJECT_SOURCE_DIR}/source/*.h.in)
|
||||
file(GLOB_RECURSE examples ${PROJECT_SOURCE_DIR}/examples/*.cpp
|
||||
${PROJECT_SOURCE_DIR}/examples/*.hpp)
|
||||
file(GLOB_RECURSE external ${PROJECT_SOURCE_DIR}/examples/lulesh/external/*.cpp
|
||||
${PROJECT_SOURCE_DIR}/examples/lulesh/external/*.hpp)
|
||||
file(GLOB_RECURSE external ${PROJECT_SOURCE_DIR}/examples/lulesh/external/kokkos/*)
|
||||
file(GLOB_RECURSE cmake_files ${PROJECT_SOURCE_DIR}/source/*CMakeLists.txt
|
||||
${PROJECT_SOURCE_DIR}/examples/*CMakeLists.txt
|
||||
${PROJECT_SOURCE_DIR}/tests/*CMakeLists.txt ${PROJECT_SOURCE_DIR}/cmake/*.cmake)
|
||||
list(APPEND cmake_files ${PROJECT_SOURCE_DIR}/CMakeLists.txt)
|
||||
if(external)
|
||||
list(REMOVE_ITEM examples ${external})
|
||||
list(REMOVE_ITEM cmake_files ${external})
|
||||
endif()
|
||||
add_custom_target(
|
||||
format-omnitrace
|
||||
format-omnitrace-source
|
||||
${OMNITRACE_CLANG_FORMAT_EXE} -i ${sources} ${headers} ${examples}
|
||||
COMMENT "Running C++ formatter ${OMNITRACE_CLANG_FORMAT_EXE}...")
|
||||
COMMENT "[omnitrace] Running C++ formatter ${OMNITRACE_CLANG_FORMAT_EXE}...")
|
||||
add_custom_target(format-omnitrace)
|
||||
add_dependencies(format-omnitrace format-omnitrace-source)
|
||||
if(NOT TARGET format)
|
||||
add_custom_target(format)
|
||||
endif()
|
||||
add_dependencies(format format-omnitrace)
|
||||
if(OMNITRACE_CMAKE_FORMAT_EXE)
|
||||
add_custom_target(
|
||||
format-omnitrace-cmake
|
||||
${OMNITRACE_CMAKE_FORMAT_EXE} -i ${cmake_files}
|
||||
COMMENT "[omnitrace] Running CMake formatter ${OMNITRACE_CMAKE_FORMAT_EXE}..."
|
||||
)
|
||||
if(NOT TARGET format-cmake)
|
||||
add_custom_target(format-cmake)
|
||||
endif()
|
||||
add_dependencies(format-cmake format-omnitrace-cmake)
|
||||
endif()
|
||||
else()
|
||||
message(
|
||||
AUTHOR_WARNING
|
||||
|
||||
@@ -350,6 +350,9 @@ set(TIMEMORY_USE_GOTCHA
|
||||
set(TIMEMORY_USE_PERFETTO
|
||||
OFF
|
||||
CACHE BOOL "Disable perfetto support in timemory")
|
||||
set(TIMEMORY_USE_OMPT
|
||||
${OMNITRACE_USE_OMPT}
|
||||
CACHE BOOL "Enable OMPT support in timemory" FORCE)
|
||||
set(TIMEMORY_USE_LIBUNWIND
|
||||
ON
|
||||
CACHE BOOL "Enable libunwind support in timemory")
|
||||
@@ -369,7 +372,9 @@ set(TIMEMORY_BUILD_EXTRA_OPTIMIZATIONS
|
||||
set(TIMEMORY_TLS_MODEL
|
||||
"global-dynamic"
|
||||
CACHE STRING "Thread-local static model" FORCE)
|
||||
|
||||
set(TIMEMORY_MAX_THREADS
|
||||
"${OMNITRACE_MAX_THREADS}"
|
||||
CACHE STRING "Max statically-allocated threads" FORCE)
|
||||
set(TIMEMORY_SETTINGS_PREFIX
|
||||
"OMNITRACE_"
|
||||
CACHE STRING "Prefix used for settings and environment variables")
|
||||
@@ -430,19 +435,24 @@ if(NOT TARGET PTL::ptl-shared)
|
||||
|
||||
omnitrace_save_variables(
|
||||
BUILD_CONFIG
|
||||
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS CMAKE_POSITION_INDEPENDENT_CODE
|
||||
CMAKE_CXX_VISIBILITY_PRESET CMAKE_VISIBILITY_INLINES_HIDDEN)
|
||||
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS BUILD_OBJECT_LIBS
|
||||
CMAKE_POSITION_INDEPENDENT_CODE CMAKE_CXX_VISIBILITY_PRESET
|
||||
CMAKE_VISIBILITY_INLINES_HIDDEN)
|
||||
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
set(BUILD_STATIC_LIBS OFF)
|
||||
set(BUILD_OBJECT_LIBS ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
|
||||
add_subdirectory(external/PTL)
|
||||
omnitrace_restore_variables(
|
||||
BUILD_CONFIG
|
||||
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS CMAKE_POSITION_INDEPENDENT_CODE
|
||||
CMAKE_CXX_VISIBILITY_PRESET CMAKE_VISIBILITY_INLINES_HIDDEN)
|
||||
VARIABLES BUILD_SHARED_LIBS BUILD_STATIC_LIBS BUILD_OBJECT_LIBS
|
||||
CMAKE_POSITION_INDEPENDENT_CODE CMAKE_CXX_VISIBILITY_PRESET
|
||||
CMAKE_VISIBILITY_INLINES_HIDDEN)
|
||||
endif()
|
||||
|
||||
target_link_libraries(omnitrace-ptl INTERFACE PTL::ptl-shared)
|
||||
target_sources(omnitrace-ptl INTERFACE $<TARGET_OBJECTS:PTL::ptl-object>)
|
||||
target_link_libraries(omnitrace-ptl INTERFACE PTL::ptl-object)
|
||||
|
||||
@@ -7,6 +7,8 @@ set(CMAKE_CXX_VISIBILITY_PRESET "default")
|
||||
|
||||
add_subdirectory(transpose)
|
||||
add_subdirectory(parallel-overhead)
|
||||
add_subdirectory(user-api)
|
||||
add_subdirectory(openmp)
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build dynamic libraries" ON)
|
||||
|
||||
|
||||
@@ -55,17 +55,3 @@ if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
||||
${CMAKE_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
if(LULESH_USE_MPI)
|
||||
add_test(
|
||||
NAME lulesh
|
||||
COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 8
|
||||
$<TARGET_FILE:${PROJECT_NAME}> -i 100 -s 20 -p
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
else()
|
||||
add_test(
|
||||
NAME lulesh
|
||||
COMMAND $<TARGET_FILE:${PROJECT_NAME}> -i 100 -s 20 -p
|
||||
WORKING_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
Fichier diff supprimé car celui-ci est trop grand
Voir la Diff
@@ -0,0 +1,23 @@
|
||||
/* CLASS = B */
|
||||
/*
|
||||
c This file is generated automatically by the setparams utility.
|
||||
c It sets the number of processors and the class_npb of the NPB
|
||||
c in this directory. Do not modify it by hand.
|
||||
*/
|
||||
#define NA 75000
|
||||
#define NONZER 13
|
||||
#define NITER 75
|
||||
#define SHIFT 60.0
|
||||
#define RCOND 1.0e-1
|
||||
#define CONVERTDOUBLE FALSE
|
||||
#define COMPILETIME "01 Mar 2022"
|
||||
#define NPBVERSION "4.1"
|
||||
#define LIBVERSION "201511"
|
||||
#define COMPILERVERSION "11.1.0"
|
||||
#define CS1 "g++ -std=c++14"
|
||||
#define CS2 "$(CC)"
|
||||
#define CS3 "-lm"
|
||||
#define CS4 "-I../common "
|
||||
#define CS5 "-O3 -fopenmp -mcmodel=medium"
|
||||
#define CS6 "-O3 -fopenmp -mcmodel=medium"
|
||||
#define CS7 "randdp"
|
||||
@@ -0,0 +1,27 @@
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
|
||||
file(GLOB common_source ${CMAKE_CURRENT_SOURCE_DIR}/common/*.cpp)
|
||||
add_library(openmp-common OBJECT ${common_source})
|
||||
target_include_directories(openmp-common PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/common)
|
||||
|
||||
add_executable(openmp-cg ${CMAKE_CURRENT_SOURCE_DIR}/CG/cg.cpp
|
||||
$<TARGET_OBJECTS:openmp-common>)
|
||||
add_executable(openmp-lu ${CMAKE_CURRENT_SOURCE_DIR}/LU/lu.cpp
|
||||
$<TARGET_OBJECTS:openmp-common>)
|
||||
|
||||
find_program(CLANGXX_EXECUTABLE NAMES clang++)
|
||||
if(CLANGXX_EXECUTABLE)
|
||||
target_compile_options(openmp-common PUBLIC -W -Wall -fopenmp=libomp)
|
||||
target_compile_options(openmp-cg PRIVATE -W -Wall -fopenmp=libomp)
|
||||
target_link_libraries(openmp-cg PRIVATE omp)
|
||||
target_compile_options(openmp-lu PRIVATE -W -Wall -fopenmp=libomp)
|
||||
target_link_libraries(openmp-lu PRIVATE omp)
|
||||
omnitrace_custom_compilation(COMPILER ${CLANGXX_EXECUTABLE} TARGET openmp-common)
|
||||
omnitrace_custom_compilation(COMPILER ${CLANGXX_EXECUTABLE} TARGET openmp-cg)
|
||||
omnitrace_custom_compilation(COMPILER ${CLANGXX_EXECUTABLE} TARGET openmp-lu)
|
||||
else()
|
||||
find_package(OpenMP REQUIRED)
|
||||
target_link_libraries(openmp-common PUBLIC OpenMP::OpenMP_CXX)
|
||||
endif()
|
||||
Fichier diff supprimé car celui-ci est trop grand
Voir la Diff
@@ -0,0 +1,27 @@
|
||||
/* CLASS = W */
|
||||
/*
|
||||
c This file is generated automatically by the setparams utility.
|
||||
c It sets the number of processors and the class_npb of the NPB
|
||||
c in this directory. Do not modify it by hand.
|
||||
*/
|
||||
|
||||
/* full problem size */
|
||||
#define ISIZ1 25
|
||||
#define ISIZ2 25
|
||||
#define ISIZ3 25
|
||||
/* number of iterations and how often to print the norm */
|
||||
#define ITMAX_DEFAULT 150
|
||||
#define INORM_DEFAULT 150
|
||||
#define DT_DEFAULT 1.5e-3
|
||||
#define CONVERTDOUBLE FALSE
|
||||
#define COMPILETIME "07 Mar 2022"
|
||||
#define NPBVERSION "4.1"
|
||||
#define LIBVERSION "201511"
|
||||
#define COMPILERVERSION "11.1.0"
|
||||
#define CS1 "g++ -std=c++14"
|
||||
#define CS2 "$(CC)"
|
||||
#define CS3 "-lm"
|
||||
#define CS4 "-I../common "
|
||||
#define CS5 "-O3 -fopenmp -mcmodel=medium"
|
||||
#define CS6 "-O3 -fopenmp -mcmodel=medium"
|
||||
#define CS7 "randdp"
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
|
||||
GMAP website: https://gmap.pucrs.br
|
||||
|
||||
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
|
||||
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The original NPB 3.4.1 version was written in Fortran and belongs to:
|
||||
http://www.nas.nasa.gov/Software/NPB/
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The serial C++ version is a translation of the original NPB 3.4.1
|
||||
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
|
||||
|
||||
Authors of the C++ code:
|
||||
Dalvan Griebler <dalvangriebler@gmail.com>
|
||||
Gabriell Araujo <hexenoften@gmail.com>
|
||||
Júnior Löff <loffjh@gmail.com>
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
/*****************************************************************/
|
||||
/****** C _ P R I N T _ R E S U L T S ******/
|
||||
/*****************************************************************/
|
||||
void
|
||||
c_print_results(char* name, char class_npb, int n1, int n2, int n3, int niter, double t,
|
||||
double mops, char* optype, int passed_verification, char* npbversion,
|
||||
char* compiletime, char* compilerversion, char* libversion,
|
||||
char* totalthreads, char* cc, char* clink, char* c_lib, char* c_inc,
|
||||
char* cflags, char* clinkflags, char* rand)
|
||||
{
|
||||
printf("\n\n %s Benchmark Completed\n", name);
|
||||
printf(" class_npb = %c\n", class_npb);
|
||||
if((name[0] == 'I') && (name[1] == 'S'))
|
||||
{
|
||||
if(n3 == 0)
|
||||
{
|
||||
long nn = n1;
|
||||
if(n2 != 0)
|
||||
{
|
||||
nn *= n2;
|
||||
}
|
||||
printf(" Size = %12ld\n", nn); /* as in IS */
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" Size = %4dx%4dx%4d\n", n1, n2, n3);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char size[16];
|
||||
int j;
|
||||
if((n2 == 0) && (n3 == 0))
|
||||
{
|
||||
if((name[0] == 'E') && (name[1] == 'P'))
|
||||
{
|
||||
sprintf(size, "%15.0lf", pow(2.0, n1));
|
||||
j = 14;
|
||||
if(size[j] == '.')
|
||||
{
|
||||
size[j] = ' ';
|
||||
j--;
|
||||
}
|
||||
size[j + 1] = '\0';
|
||||
printf(" Size = %15s\n", size);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" Size = %12d\n", n1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" Size = %4dx%4dx%4d\n", n1, n2, n3);
|
||||
}
|
||||
}
|
||||
printf(" Total threads = %12s\n", totalthreads);
|
||||
printf(" Iterations = %12d\n", niter);
|
||||
printf(" Time in seconds = %12.2f\n", t);
|
||||
printf(" Mop/s total = %12.2f\n", mops);
|
||||
printf(" Operation type = %24s\n", optype);
|
||||
if(passed_verification < 0)
|
||||
{
|
||||
printf(" Verification = NOT PERFORMED\n");
|
||||
}
|
||||
else if(passed_verification)
|
||||
{
|
||||
printf(" Verification = SUCCESSFUL\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" Verification = UNSUCCESSFUL\n");
|
||||
}
|
||||
printf(" Version = %12s\n", npbversion);
|
||||
printf(" Compile date = %12s\n", compiletime);
|
||||
printf(" Compiler ver = %12s\n", compilerversion);
|
||||
printf(" OpenMP version = %12s\n", libversion);
|
||||
printf("\n Compile options:\n");
|
||||
printf(" CC = %s\n", cc);
|
||||
printf(" CLINK = %s\n", clink);
|
||||
printf(" C_LIB = %s\n", c_lib);
|
||||
printf(" C_INC = %s\n", c_inc);
|
||||
printf(" CFLAGS = %s\n", cflags);
|
||||
printf(" CLINKFLAGS = %s\n", clinkflags);
|
||||
printf(" RAND = %s\n", rand);
|
||||
#ifdef SMP
|
||||
evalue = getenv("MP_SET_NUMTHREADS");
|
||||
printf(" MULTICPUS = %s\n", evalue);
|
||||
#endif
|
||||
/*
|
||||
* printf(" Please send the results of this run to:\n\n");
|
||||
* printf(" NPB Development Team\n");
|
||||
* printf(" Internet: npb@nas.nasa.gov\n \n");
|
||||
* printf(" If email is not available, send this to:\n\n");
|
||||
* printf(" MS T27A-1\n");
|
||||
* printf(" NASA Ames Research Center\n");
|
||||
* printf(" Moffett Field, CA 94035-1000\n\n");
|
||||
* printf(" Fax: 650-604-3957\n\n");
|
||||
*/
|
||||
printf("\n\n");
|
||||
|
||||
printf("----------------------------------------------------------------------\n");
|
||||
printf(" NPB-CPP is developed by: \n");
|
||||
printf(" Dalvan Griebler\n");
|
||||
printf(" Gabriell Araujo (Sequential Porting)\n");
|
||||
printf(" Júnior Löff (Parallel Implementation)\n");
|
||||
printf("\n");
|
||||
printf(" In case of questions or problems, please send an e-mail to us:\n");
|
||||
printf(" dalvan.griebler; gabriell.araujo; junior.loff@edu.pucrs.br\n");
|
||||
printf("----------------------------------------------------------------------\n");
|
||||
printf("\n");
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
|
||||
GMAP website: https://gmap.pucrs.br
|
||||
|
||||
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
|
||||
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The original NPB 3.4.1 version was written in Fortran and belongs to:
|
||||
http://www.nas.nasa.gov/Software/NPB/
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The serial C++ version is a translation of the original NPB 3.4.1
|
||||
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
|
||||
|
||||
Authors of the C++ code:
|
||||
Dalvan Griebler <dalvangriebler@gmail.com>
|
||||
Gabriell Araujo <hexenoften@gmail.com>
|
||||
Júnior Löff <loffjh@gmail.com>
|
||||
*/
|
||||
|
||||
#if defined(USE_POW)
|
||||
# define r23 pow(0.5, 23.0)
|
||||
# define r46 (r23 * r23)
|
||||
# define t23 pow(2.0, 23.0)
|
||||
# define t46 (t23 * t23)
|
||||
#else
|
||||
# define r23 \
|
||||
(0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * \
|
||||
0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5 * 0.5)
|
||||
# define r46 (r23 * r23)
|
||||
# define t23 \
|
||||
(2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * \
|
||||
2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0 * 2.0)
|
||||
# define t46 (t23 * t23)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* this routine returns a uniform pseudorandom double precision number in the
|
||||
* range (0, 1) by using the linear congruential generator
|
||||
*
|
||||
* x_{k+1} = a x_k (mod 2^46)
|
||||
*
|
||||
* where 0 < x_k < 2^46 and 0 < a < 2^46. this scheme generates 2^44 numbers
|
||||
* before repeating. the argument A is the same as 'a' in the above formula,
|
||||
* and X is the same as x_0. A and X must be odd double precision integers
|
||||
* in the range (1, 2^46). the returned value RANDLC is normalized to be
|
||||
* between 0 and 1, i.e. RANDLC = 2^(-46) * x_1. X is updated to contain
|
||||
* the new seed x_1, so that subsequent calls to RANDLC using the same
|
||||
* arguments will generate a continuous sequence.
|
||||
*
|
||||
* this routine should produce the same results on any computer with at least
|
||||
* 48 mantissa bits in double precision floating point data. On 64 bit
|
||||
* systems, double precision should be disabled.
|
||||
*
|
||||
* David H. Bailey, October 26, 1990
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
double
|
||||
randlc(double* x, double a)
|
||||
{
|
||||
double t1, t2, t3, t4, a1, a2, x1, x2, z;
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
* break A into two parts such that A = 2^23 * A1 + A2.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
t1 = r23 * a;
|
||||
a1 = (int) t1;
|
||||
a2 = a - t23 * a1;
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
* break X into two parts such that X = 2^23 * X1 + X2, compute
|
||||
* Z = A1 * X2 + A2 * X1 (mod 2^23), and then
|
||||
* X = 2^23 * Z + A2 * X2 (mod 2^46).
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
t1 = r23 * (*x);
|
||||
x1 = (int) t1;
|
||||
x2 = (*x) - t23 * x1;
|
||||
t1 = a1 * x2 + a2 * x1;
|
||||
t2 = (int) (r23 * t1);
|
||||
z = t1 - t23 * t2;
|
||||
t3 = t23 * z + a2 * x2;
|
||||
t4 = (int) (r46 * t3);
|
||||
(*x) = t3 - t46 * t4;
|
||||
|
||||
return (r46 * (*x));
|
||||
}
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
*
|
||||
* this routine generates N uniform pseudorandom double precision numbers in
|
||||
* the range (0, 1) by using the linear congruential generator
|
||||
*
|
||||
* x_{k+1} = a x_k (mod 2^46)
|
||||
*
|
||||
* where 0 < x_k < 2^46 and 0 < a < 2^46. this scheme generates 2^44 numbers
|
||||
* before repeating. the argument A is the same as 'a' in the above formula,
|
||||
* and X is the same as x_0. A and X must be odd double precision integers
|
||||
* in the range (1, 2^46). the N results are placed in Y and are normalized
|
||||
* to be between 0 and 1. X is updated to contain the new seed, so that
|
||||
* subsequent calls to VRANLC using the same arguments will generate a
|
||||
* continuous sequence. if N is zero, only initialization is performed, and
|
||||
* the variables X, A and Y are ignored.
|
||||
*
|
||||
* this routine is the standard version designed for scalar or RISC systems.
|
||||
* however, it should produce the same results on any single processor
|
||||
* computer with at least 48 mantissa bits in double precision floating point
|
||||
* data. on 64 bit systems, double precision should be disabled.
|
||||
*
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
void
|
||||
vranlc(int n, double* x_seed, double a, double y[])
|
||||
{
|
||||
int i;
|
||||
double x, t1, t2, t3, t4, a1, a2, x1, x2, z;
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
* break A into two parts such that A = 2^23 * A1 + A2.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
t1 = r23 * a;
|
||||
a1 = (int) t1;
|
||||
a2 = a - t23 * a1;
|
||||
x = *x_seed;
|
||||
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
* generate N results. this loop is not vectorizable.
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
for(i = 0; i < n; i++)
|
||||
{
|
||||
/*
|
||||
* ---------------------------------------------------------------------
|
||||
* break X into two parts such that X = 2^23 * X1 + X2, compute
|
||||
* Z = A1 * X2 + A2 * X1 (mod 2^23), and then
|
||||
* X = 2^23 * Z + A2 * X2 (mod 2^46).
|
||||
* ---------------------------------------------------------------------
|
||||
*/
|
||||
t1 = r23 * x;
|
||||
x1 = (int) t1;
|
||||
x2 = x - t23 * x1;
|
||||
t1 = a1 * x2 + a2 * x1;
|
||||
t2 = (int) (r23 * t1);
|
||||
z = t1 - t23 * t2;
|
||||
t3 = t23 * z + a2 * x2;
|
||||
t4 = (int) (r46 * t3);
|
||||
x = t3 - t46 * t4;
|
||||
y[i] = r46 * x;
|
||||
}
|
||||
*x_seed = x;
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
|
||||
GMAP website: https://gmap.pucrs.br
|
||||
|
||||
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
|
||||
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The original NPB 3.4.1 version was written in Fortran and belongs to:
|
||||
http://www.nas.nasa.gov/Software/NPB/
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The serial C++ version is a translation of the original NPB 3.4.1
|
||||
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
|
||||
|
||||
Authors of the C++ code:
|
||||
Dalvan Griebler <dalvangriebler@gmail.com>
|
||||
Gabriell Araujo <hexenoften@gmail.com>
|
||||
Júnior Löff <loffjh@gmail.com>
|
||||
*/
|
||||
|
||||
#include "wtime.hpp"
|
||||
#include <cstdlib>
|
||||
|
||||
/* prototype */
|
||||
void
|
||||
wtime(double*);
|
||||
|
||||
/*****************************************************************/
|
||||
/****** E L A P S E D _ T I M E ******/
|
||||
/*****************************************************************/
|
||||
double
|
||||
elapsed_time(void)
|
||||
{
|
||||
double t;
|
||||
wtime(&t);
|
||||
return (t);
|
||||
}
|
||||
|
||||
double start[64], elapsed[64];
|
||||
|
||||
/*****************************************************************/
|
||||
/****** T I M E R _ C L E A R ******/
|
||||
/*****************************************************************/
|
||||
void
|
||||
timer_clear(int n)
|
||||
{
|
||||
elapsed[n] = 0.0;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/****** T I M E R _ S T A R T ******/
|
||||
/*****************************************************************/
|
||||
void
|
||||
timer_start(int n)
|
||||
{
|
||||
start[n] = elapsed_time();
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/****** T I M E R _ S T O P ******/
|
||||
/*****************************************************************/
|
||||
void
|
||||
timer_stop(int n)
|
||||
{
|
||||
double t, now;
|
||||
now = elapsed_time();
|
||||
t = now - start[n];
|
||||
elapsed[n] += t;
|
||||
}
|
||||
|
||||
/*****************************************************************/
|
||||
/****** T I M E R _ R E A D ******/
|
||||
/*****************************************************************/
|
||||
double
|
||||
timer_read(int n)
|
||||
{
|
||||
return (elapsed[n]);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
|
||||
GMAP website: https://gmap.pucrs.br
|
||||
|
||||
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
|
||||
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The original NPB 3.4.1 version was written in Fortran and belongs to:
|
||||
http://www.nas.nasa.gov/Software/NPB/
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The serial C++ version is a translation of the original NPB 3.4.1
|
||||
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
|
||||
|
||||
Authors of the C++ code:
|
||||
Dalvan Griebler <dalvangriebler@gmail.com>
|
||||
Gabriell Araujo <hexenoften@gmail.com>
|
||||
Júnior Löff <loffjh@gmail.com>
|
||||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
typedef int boolean;
|
||||
typedef struct
|
||||
{
|
||||
double real;
|
||||
double imag;
|
||||
} dcomplex;
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define pow2(a) ((a) * (a))
|
||||
|
||||
/* old version of the complex number operations */
|
||||
#define get_real(c) c.real
|
||||
#define get_imag(c) c.imag
|
||||
#define cadd(c, a, b) (c.real = a.real + b.real, c.imag = a.imag + b.imag)
|
||||
#define csub(c, a, b) (c.real = a.real - b.real, c.imag = a.imag - b.imag)
|
||||
#define cmul(c, a, b) \
|
||||
(c.real = a.real * b.real - a.imag * b.imag, \
|
||||
c.imag = a.real * b.imag + a.imag * b.real)
|
||||
#define crmul(c, a, b) (c.real = a.real * b, c.imag = a.imag * b)
|
||||
|
||||
/* latest version of the complex number operations */
|
||||
#define dcomplex_create(r, i) \
|
||||
(dcomplex) { r, i }
|
||||
#define dcomplex_add(a, b) \
|
||||
(dcomplex) { (a).real + (b).real, (a).imag + (b).imag }
|
||||
#define dcomplex_sub(a, b) \
|
||||
(dcomplex) { (a).real - (b).real, (a).imag - (b).imag }
|
||||
#define dcomplex_mul(a, b) \
|
||||
(dcomplex) \
|
||||
{ \
|
||||
((a).real * (b).real) - ((a).imag * (b).imag), \
|
||||
((a).real * (b).imag) + ((a).imag * (b).real) \
|
||||
}
|
||||
#define dcomplex_mul2(a, b) \
|
||||
(dcomplex) { (a).real*(b), (a).imag*(b) }
|
||||
static inline dcomplex
|
||||
dcomplex_div(dcomplex z1, dcomplex z2)
|
||||
{
|
||||
double a = z1.real;
|
||||
double b = z1.imag;
|
||||
double c = z2.real;
|
||||
double d = z2.imag;
|
||||
double divisor = c * c + d * d;
|
||||
double real = (a * c + b * d) / divisor;
|
||||
double imag = (b * c - a * d) / divisor;
|
||||
dcomplex result = (dcomplex){ real, imag };
|
||||
return result;
|
||||
}
|
||||
#define dcomplex_div2(a, b) \
|
||||
(dcomplex) { (a).real / (b), (a).imag / (b) }
|
||||
#define dcomplex_abs(x) sqrt(((x).real * (x).real) + ((x).imag * (x).imag))
|
||||
#define dconjg(x) \
|
||||
(dcomplex) { (x).real, -1.0 * (x).imag }
|
||||
|
||||
extern double
|
||||
randlc(double*, double);
|
||||
extern void
|
||||
vranlc(int, double*, double, double*);
|
||||
extern void
|
||||
timer_clear(int);
|
||||
extern void
|
||||
timer_start(int);
|
||||
extern void
|
||||
timer_stop(int);
|
||||
extern double
|
||||
timer_read(int);
|
||||
|
||||
extern void
|
||||
c_print_results(char* name, char class_npb, int n1, int n2, int n3, int niter, double t,
|
||||
double mops, char* optype, int passed_verification, char* npbversion,
|
||||
char* compiletime, char* compilerversion, char* libversion,
|
||||
char* totalthreads, char* cc, char* clink, char* c_lib, char* c_inc,
|
||||
char* cflags, char* clinkflags, char* rand);
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
|
||||
GMAP website: https://gmap.pucrs.br
|
||||
|
||||
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
|
||||
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The original NPB 3.4.1 version was written in Fortran and belongs to:
|
||||
http://www.nas.nasa.gov/Software/NPB/
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The serial C++ version is a translation of the original NPB 3.4.1
|
||||
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
|
||||
|
||||
Authors of the C++ code:
|
||||
Dalvan Griebler <dalvangriebler@gmail.com>
|
||||
Gabriell Araujo <hexenoften@gmail.com>
|
||||
Júnior Löff <loffjh@gmail.com>
|
||||
*/
|
||||
|
||||
#include "wtime.hpp"
|
||||
#include <sys/time.h>
|
||||
|
||||
void
|
||||
wtime(double* t)
|
||||
{
|
||||
static int sec = -1;
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, 0);
|
||||
if(sec < 0) sec = tv.tv_sec;
|
||||
*t = (tv.tv_sec - sec) + 1.0e-6 * tv.tv_usec;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2021 Parallel Applications Modelling Group - GMAP
|
||||
GMAP website: https://gmap.pucrs.br
|
||||
|
||||
Pontifical Catholic University of Rio Grande do Sul (PUCRS)
|
||||
Av. Ipiranga, 6681, Porto Alegre - Brazil, 90619-900
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The original NPB 3.4.1 version was written in Fortran and belongs to:
|
||||
http://www.nas.nasa.gov/Software/NPB/
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
The serial C++ version is a translation of the original NPB 3.4.1
|
||||
Serial C++ version: https://github.com/GMAP/NPB-CPP/tree/master/NPB-SER
|
||||
|
||||
Authors of the C++ code:
|
||||
Dalvan Griebler <dalvangriebler@gmail.com>
|
||||
Gabriell Araujo <hexenoften@gmail.com>
|
||||
Júnior Löff <loffjh@gmail.com>
|
||||
*/
|
||||
|
||||
/*
|
||||
* C/Fortran interface is different on different machines.
|
||||
* you may need to tweak this.
|
||||
*/
|
||||
#if defined(IBM)
|
||||
# define wtime wtime
|
||||
#elif defined(CRAY)
|
||||
# define wtime WTIME
|
||||
#else
|
||||
# define wtime wtime_
|
||||
#endif
|
||||
@@ -95,7 +95,7 @@ transpose_a(int* in, int* out, int M, int N)
|
||||
void
|
||||
run(int rank, int tid, hipStream_t stream, int argc, char** argv)
|
||||
{
|
||||
size_t nitr = 5000;
|
||||
size_t nitr = 500;
|
||||
unsigned int M = 4960 * 2;
|
||||
unsigned int N = 4960 * 2;
|
||||
if(argc > 2) nitr = atoll(argv[2]);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.15 FATAL_ERROR)
|
||||
|
||||
project(omnitrace-user-api LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
find_package(Threads REQUIRED)
|
||||
add_executable(user-api user-api.cpp)
|
||||
target_link_libraries(user-api PRIVATE Threads::Threads omnitrace::omnitrace-user-library)
|
||||
|
||||
if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
|
||||
set_target_properties(user-api PROPERTIES RUNTIME_OUTPUT_DIRECTORY
|
||||
${CMAKE_BINARY_DIR})
|
||||
endif()
|
||||
@@ -0,0 +1,80 @@
|
||||
|
||||
#include <omnitrace/user.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
std::atomic<long> total{ 0 };
|
||||
|
||||
long
|
||||
fib(long n) __attribute__((noinline));
|
||||
|
||||
void
|
||||
run(size_t nitr, long) __attribute__((noinline));
|
||||
|
||||
long
|
||||
fib(long n)
|
||||
{
|
||||
return (n < 2) ? n : fib(n - 1) + fib(n - 2);
|
||||
}
|
||||
|
||||
#define RUN_LABEL \
|
||||
std::string{ std::string{ __FUNCTION__ } + "(" + std::to_string(n) + ") x " + \
|
||||
std::to_string(nitr) } \
|
||||
.c_str()
|
||||
|
||||
void
|
||||
run(size_t nitr, long n)
|
||||
{
|
||||
omnitrace_user_stop_thread_trace();
|
||||
omnitrace_user_push_region(RUN_LABEL);
|
||||
long local = 0;
|
||||
for(size_t i = 0; i < nitr; ++i)
|
||||
local += fib(n);
|
||||
total += local;
|
||||
omnitrace_user_pop_region(RUN_LABEL);
|
||||
omnitrace_user_start_thread_trace();
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char** argv)
|
||||
{
|
||||
omnitrace_user_push_region(argv[0]);
|
||||
omnitrace_user_push_region("initialization");
|
||||
size_t nthread = std::min<size_t>(16, std::thread::hardware_concurrency());
|
||||
size_t nitr = 50000;
|
||||
long nfib = 10;
|
||||
if(argc > 1) nfib = atol(argv[1]);
|
||||
if(argc > 2) nthread = atol(argv[2]);
|
||||
if(argc > 3) nitr = atol(argv[3]);
|
||||
omnitrace_user_pop_region("initialization");
|
||||
|
||||
printf("[%s] Threads: %zu\n[%s] Iterations: %zu\n[%s] fibonacci(%li)...\n", argv[0],
|
||||
nthread, argv[0], nitr, argv[0], nfib);
|
||||
|
||||
omnitrace_user_push_region("thread_creation");
|
||||
std::vector<std::thread> threads{};
|
||||
threads.reserve(nthread);
|
||||
for(size_t i = 0; i < nthread; ++i)
|
||||
{
|
||||
size_t _nitr = ((i % 2) == 1) ? (nitr - (0.1 * nitr)) : (nitr + (0.1 * nitr));
|
||||
threads.emplace_back(&run, _nitr, nfib);
|
||||
}
|
||||
omnitrace_user_pop_region("thread_creation");
|
||||
|
||||
run(nitr - 0.25 * nitr, nfib - 0.1 * nfib);
|
||||
|
||||
omnitrace_user_push_region("thread_wait");
|
||||
for(auto& itr : threads)
|
||||
itr.join();
|
||||
omnitrace_user_pop_region("thread_wait");
|
||||
|
||||
printf("[%s] fibonacci(%li) x %lu = %li\n", argv[0], nfib, nthread, total.load());
|
||||
omnitrace_user_pop_region(argv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Externe
+1
-1
Sous-module external/PTL mis-à-jour : 61f873cf79...4afd2bdeb9
Externe
+1
-1
Sous-module external/timemory mis-à-jour : b8d3b3e1fd...1ea2511833
@@ -12,3 +12,13 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR})
|
||||
|
||||
add_subdirectory(lib)
|
||||
add_subdirectory(bin)
|
||||
|
||||
if(OMNITRACE_BUILD_DEVELOPER)
|
||||
add_custom_target(omnitrace-precommit)
|
||||
foreach(_TARGET format-omnitrace-source format-omnitrace-cmake format-timemory-source
|
||||
format-timemory-cmake)
|
||||
if(TARGET ${_TARGET})
|
||||
add_dependencies(omnitrace-precommit ${_TARGET})
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
add_subdirectory(omnitrace-avail)
|
||||
add_subdirectory(omnitrace-critical-trace)
|
||||
add_subdirectory(omnitrace)
|
||||
|
||||
if(OMNITRACE_BUILD_TESTING)
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "library/components/omnitrace.hpp"
|
||||
#include "library/components/pthread_gotcha.hpp"
|
||||
#include "library/components/roctracer.hpp"
|
||||
#include "library/components/user_region.hpp"
|
||||
#include "library/config.hpp"
|
||||
|
||||
#include <timemory/components.hpp>
|
||||
@@ -613,8 +614,6 @@ main(int argc, char** argv)
|
||||
|
||||
if(!os) os = &std::cout;
|
||||
|
||||
omnitrace_init_library();
|
||||
|
||||
if(include_components) write_component_info(*os, options, use_mark, fields);
|
||||
|
||||
dump_log();
|
||||
@@ -766,7 +765,9 @@ write_component_info(std::ostream& os, const array_t<bool, N>& options,
|
||||
_mark.at(i));
|
||||
}
|
||||
|
||||
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
|
||||
if(!category_regex_keys.empty())
|
||||
_selected +=
|
||||
(is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
|
||||
|
||||
if(_selected == 0) continue;
|
||||
}
|
||||
@@ -834,7 +835,8 @@ write_component_info(std::ostream& os, const array_t<bool, N>& options,
|
||||
_mark.at(i));
|
||||
}
|
||||
|
||||
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
|
||||
if(!category_regex_keys.empty())
|
||||
_selected += (is_category_selected(std::get<2>(itr).at(CATEGORY))) ? 1 : 0;
|
||||
|
||||
if(_selected > 0)
|
||||
{
|
||||
|
||||
@@ -4,10 +4,19 @@
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
add_executable(
|
||||
add_executable(omnitrace-exe ${_EXCLUDE})
|
||||
|
||||
target_sources(
|
||||
omnitrace-exe
|
||||
${_EXCLUDE} ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp ${CMAKE_CURRENT_LIST_DIR}/details.cpp)
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/omnitrace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/details.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/function_signature.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/module_function.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/omnitrace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/info.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/fwd.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/function_signature.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/module_function.hpp)
|
||||
|
||||
target_link_libraries(
|
||||
omnitrace-exe
|
||||
|
||||
@@ -40,7 +40,7 @@ get_whole_function_names()
|
||||
"backtrace", "backtrace_symbols", "backtrace_symbols_fd", "sigaddset",
|
||||
"sigandset", "sigdelset", "sigemptyset", "sigfillset", "sighold", "sigisemptyset",
|
||||
"sigismember", "sigorset", "sigrelse", "sigvec", "strtok", "strstr", "sbrk",
|
||||
"strxfrm",
|
||||
"strxfrm", "atexit", "ompt_start_tool", "nanosleep",
|
||||
// below are functions which never terminate
|
||||
"rocr::core::Signal::WaitAny", "rocr::core::Runtime::AsyncEventsLoop",
|
||||
"rocr::core::BusyWaitSignal::WaitAcquire",
|
||||
@@ -525,10 +525,32 @@ are_file_include_exclude_lists_empty()
|
||||
// the instrumented loop and formats it properly.
|
||||
//
|
||||
function_signature
|
||||
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
|
||||
get_loop_file_line_info(module_t* module, procedure_t* func, flow_graph_t* cfGraph,
|
||||
basic_loop_t* loopToInstrument)
|
||||
{
|
||||
if(!cfGraph || !loopToInstrument || !f) return function_signature{ "", "", "" };
|
||||
if(!cfGraph || !loopToInstrument || !func) return function_signature{ "", "", "" };
|
||||
|
||||
std::vector<BPatch_basicBlock*> basic_blocks{};
|
||||
loopToInstrument->getLoopBasicBlocksExclusive(basic_blocks);
|
||||
|
||||
if(basic_blocks.empty()) return function_signature{ "", "", "" };
|
||||
|
||||
auto base_addr = basic_blocks.front()->getStartAddress();
|
||||
auto last_addr = basic_blocks.front()->getEndAddress();
|
||||
basic_block_t* block = basic_blocks.front();
|
||||
for(const auto& itr : basic_blocks)
|
||||
{
|
||||
if(itr == block) continue;
|
||||
if(itr->dominates(block))
|
||||
{
|
||||
base_addr = itr->getStartAddress();
|
||||
last_addr = itr->getEndAddress();
|
||||
block = itr;
|
||||
}
|
||||
}
|
||||
|
||||
verbprintf(4, "Loop: size = %lu: base_addr = %lu, last_addr = %lu\n",
|
||||
(unsigned long) (last_addr - base_addr), base_addr, last_addr);
|
||||
|
||||
char fname[FUNCNAMELEN + 1];
|
||||
char mname[FUNCNAMELEN + 1];
|
||||
@@ -537,32 +559,14 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
mutatee_module->getName(mname, FUNCNAMELEN);
|
||||
module->getName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
bpvector_t<point_t*>* loopStartInst =
|
||||
cfGraph->findLoopInstPoints(BPatch_locLoopStartIter, loopToInstrument);
|
||||
bpvector_t<point_t*>* loopExitInst =
|
||||
cfGraph->findLoopInstPoints(BPatch_locLoopEndIter, loopToInstrument);
|
||||
auto* returnType = func->getReturnType();
|
||||
|
||||
if(!loopStartInst || !loopExitInst) return function_signature{ "", "", "" };
|
||||
if(returnType) typeName = returnType->getName();
|
||||
|
||||
unsigned long baseAddr = (unsigned long) (*loopStartInst)[0]->getAddress();
|
||||
unsigned long lastAddr =
|
||||
(unsigned long) (*loopExitInst)[loopExitInst->size() - 1]->getAddress();
|
||||
verbprintf(3, "Loop: size of lastAddr = %lu: baseAddr = %lu, lastAddr = %lu\n",
|
||||
(unsigned long) loopExitInst->size(), (unsigned long) baseAddr,
|
||||
(unsigned long) lastAddr);
|
||||
|
||||
f->getName(fname, FUNCNAMELEN);
|
||||
|
||||
auto* returnType = f->getReturnType();
|
||||
|
||||
if(returnType)
|
||||
{
|
||||
typeName = returnType->getName();
|
||||
}
|
||||
|
||||
auto* params = f->getParams();
|
||||
auto* params = func->getParams();
|
||||
std::vector<string_t> _params;
|
||||
if(params)
|
||||
{
|
||||
@@ -574,36 +578,51 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
|
||||
}
|
||||
}
|
||||
|
||||
bpvector_t<BPatch_statement> lines;
|
||||
bpvector_t<BPatch_statement> linesEnd;
|
||||
bpvector_t<BPatch_statement> lines{};
|
||||
bpvector_t<BPatch_statement> linesEnd{};
|
||||
|
||||
bool info1 = mutatee_module->getSourceLines(baseAddr, lines);
|
||||
bool info1 = module->getSourceLines(base_addr, lines);
|
||||
|
||||
string_t filename = mname;
|
||||
|
||||
if(info1)
|
||||
{
|
||||
// filename = lines[0].fileName();
|
||||
auto row1 = lines[0].lineNumber();
|
||||
auto col1 = lines[0].lineOffset();
|
||||
int row1 = 0;
|
||||
int col1 = 0;
|
||||
for(auto& itr : lines)
|
||||
{
|
||||
if(itr.lineNumber() > 0)
|
||||
{
|
||||
row1 = itr.lineNumber();
|
||||
col1 = itr.lineOffset();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(row1 == 0 && col1 == 0)
|
||||
return function_signature(typeName, fname, filename, _params);
|
||||
|
||||
int row2 = 0;
|
||||
int col2 = 0;
|
||||
for(auto& itr : lines)
|
||||
{
|
||||
row2 = std::max(row2, itr.lineNumber());
|
||||
col2 = std::max(col2, itr.lineOffset());
|
||||
}
|
||||
|
||||
if(col1 < 0) col1 = 0;
|
||||
|
||||
// This following section is attempting to remedy the limitations of
|
||||
// getSourceLines for loops. As the program goes through the loop, the resulting
|
||||
// lines go from the loop head, through the instructions present in the loop, to
|
||||
// the last instruction in the loop, back to the loop head, then to the next
|
||||
// instruction outside of the loop. What this section does is starts at the last
|
||||
// instruction in the loop, then goes through the addresses until it reaches the
|
||||
// next instruction outside of the loop. We then bump back a line. This is not a
|
||||
// perfect solution, but we will work with the Dyninst team to find something
|
||||
// better.
|
||||
bool info2 = mutatee_module->getSourceLines((unsigned long) lastAddr, linesEnd);
|
||||
verbprintf(3, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
|
||||
bool info2 = module->getSourceLines(last_addr, linesEnd);
|
||||
verbprintf(4, "size of linesEnd = %lu\n", (unsigned long) linesEnd.size());
|
||||
|
||||
if(info2)
|
||||
{
|
||||
auto row2 = linesEnd[0].lineNumber();
|
||||
auto col2 = linesEnd[0].lineOffset();
|
||||
for(auto& itr : linesEnd)
|
||||
{
|
||||
row2 = std::max(row2, itr.lineNumber());
|
||||
col2 = std::max(col2, itr.lineOffset());
|
||||
}
|
||||
if(col2 < 0) col2 = 0;
|
||||
if(row2 < row1) row1 = row2; // Fix for wrong line numbers
|
||||
|
||||
@@ -627,35 +646,30 @@ get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t*
|
||||
// We create a new name that embeds the file and line information in the name
|
||||
//
|
||||
function_signature
|
||||
get_func_file_line_info(module_t* mutatee_module, procedure_t* f)
|
||||
get_func_file_line_info(module_t* module, procedure_t* func)
|
||||
{
|
||||
bool info1, info2;
|
||||
unsigned long baseAddr, lastAddr;
|
||||
char fname[FUNCNAMELEN + 1];
|
||||
char mname[FUNCNAMELEN + 1];
|
||||
int row1, col1, row2, col2;
|
||||
string_t filename = {};
|
||||
string_t typeName = {};
|
||||
using address_t = Dyninst::Address;
|
||||
|
||||
char fname[FUNCNAMELEN + 1];
|
||||
char mname[FUNCNAMELEN + 1];
|
||||
string_t typeName = {};
|
||||
|
||||
memset(fname, '\0', FUNCNAMELEN + 1);
|
||||
memset(mname, '\0', FUNCNAMELEN + 1);
|
||||
|
||||
mutatee_module->getName(mname, FUNCNAMELEN);
|
||||
module->getName(mname, FUNCNAMELEN);
|
||||
func->getName(fname, FUNCNAMELEN);
|
||||
|
||||
baseAddr = (unsigned long) (f->getBaseAddr());
|
||||
f->getAddressRange(baseAddr, lastAddr);
|
||||
bpvector_t<BPatch_statement> lines;
|
||||
f->getName(fname, FUNCNAMELEN);
|
||||
address_t base_addr{};
|
||||
address_t last_addr{};
|
||||
func->getAddressRange(base_addr, last_addr);
|
||||
|
||||
auto* returnType = f->getReturnType();
|
||||
auto* returnType = func->getReturnType();
|
||||
|
||||
if(returnType)
|
||||
{
|
||||
typeName = returnType->getName();
|
||||
}
|
||||
if(returnType) typeName = returnType->getName();
|
||||
|
||||
auto* params = f->getParams();
|
||||
std::vector<string_t> _params;
|
||||
auto* params = func->getParams();
|
||||
std::vector<string_t> _params = {};
|
||||
if(params)
|
||||
{
|
||||
for(auto* itr : *params)
|
||||
@@ -666,32 +680,16 @@ get_func_file_line_info(module_t* mutatee_module, procedure_t* f)
|
||||
}
|
||||
}
|
||||
|
||||
info1 = mutatee_module->getSourceLines((unsigned long) baseAddr, lines);
|
||||
bpvector_t<BPatch_statement> lines = {};
|
||||
bool info = module->getSourceLines(base_addr, lines);
|
||||
|
||||
filename = mname;
|
||||
string_t filename = mname;
|
||||
|
||||
if(info1)
|
||||
if(info && !lines.empty())
|
||||
{
|
||||
// filename = lines[0].fileName();
|
||||
row1 = lines[0].lineNumber();
|
||||
col1 = lines[0].lineOffset();
|
||||
|
||||
if(col1 < 0) col1 = 0;
|
||||
info2 = mutatee_module->getSourceLines((unsigned long) (lastAddr - 1), lines);
|
||||
if(info2)
|
||||
{
|
||||
row2 = lines[1].lineNumber();
|
||||
col2 = lines[1].lineOffset();
|
||||
if(col2 < 0) col2 = 0;
|
||||
if(row2 < row1) row1 = row2;
|
||||
return function_signature(typeName, fname, filename, _params, { row1, 0 },
|
||||
{ 0, 0 }, false, info1, info2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return function_signature(typeName, fname, filename, _params, { row1, 0 },
|
||||
{ 0, 0 }, false, info1, info2);
|
||||
}
|
||||
auto row = lines.front().lineNumber();
|
||||
return function_signature(typeName, fname, filename, _params, { row, 0 },
|
||||
{ 0, 0 }, false, info, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "function_signature.hpp"
|
||||
|
||||
function_signature::function_signature(string_t _ret, const string_t& _name,
|
||||
string_t _file, location_t _row, location_t _col,
|
||||
bool _loop, bool _info_beg, bool _info_end)
|
||||
: m_loop(_loop)
|
||||
, m_info_beg(_info_beg)
|
||||
, m_info_end(_info_end)
|
||||
, m_row(std::move(_row))
|
||||
, m_col(std::move(_col))
|
||||
, m_return(std::move(_ret))
|
||||
, m_name(tim::demangle(_name))
|
||||
, m_file(std::move(_file))
|
||||
{
|
||||
if(m_file.find('/') != string_t::npos)
|
||||
m_file = m_file.substr(m_file.find_last_of('/') + 1);
|
||||
}
|
||||
|
||||
function_signature::function_signature(const string_t& _ret, const string_t& _name,
|
||||
const string_t& _file,
|
||||
const std::vector<string_t>& _params,
|
||||
location_t _row, location_t _col, bool _loop,
|
||||
bool _info_beg, bool _info_end)
|
||||
: function_signature(_ret, _name, _file, _row, _col, _loop, _info_beg, _info_end)
|
||||
{
|
||||
m_params = "(";
|
||||
for(const auto& itr : _params)
|
||||
m_params.append(itr + ", ");
|
||||
if(!_params.empty()) m_params = m_params.substr(0, m_params.length() - 2);
|
||||
m_params += ")";
|
||||
}
|
||||
|
||||
string_t
|
||||
function_signature::get(function_signature& sig)
|
||||
{
|
||||
return sig.get();
|
||||
}
|
||||
|
||||
string_t
|
||||
function_signature::get() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
if(use_return_info && !m_return.empty()) ss << m_return << " ";
|
||||
ss << m_name;
|
||||
if(use_args_info) ss << m_params;
|
||||
if(m_loop && m_info_beg)
|
||||
{
|
||||
auto _row_col_str = [](unsigned long _row, unsigned long _col) {
|
||||
std::stringstream _ss{};
|
||||
if(_row == 0 && _col == 0) return std::string{};
|
||||
if(_col > 0)
|
||||
_ss << "{" << _row << "," << _col << "}";
|
||||
else
|
||||
_ss << "{" << _row << "}";
|
||||
return _ss.str();
|
||||
};
|
||||
|
||||
auto _rc1 = _row_col_str(m_row.first, m_col.first);
|
||||
auto _rc2 = _row_col_str(m_row.second, m_col.second);
|
||||
if(m_info_end && !_rc1.empty() && !_rc2.empty() && _rc1 != _rc2)
|
||||
ss << " [" << _rc1 << "-" << _rc2 << "]";
|
||||
else if(m_info_end && !_rc1.empty() && !_rc2.empty() && _rc1 == _rc2)
|
||||
ss << " [" << _rc1 << "]";
|
||||
else if(m_info_end && !_rc1.empty() && _rc2.empty())
|
||||
ss << " [" << _rc1 << "]";
|
||||
else if(!m_info_end && !_rc1.empty())
|
||||
ss << " [" << _rc1 << "]";
|
||||
else
|
||||
errprintf(1, "loop line info is empty!");
|
||||
}
|
||||
if(use_file_info && m_file.length() > 0) ss << " [" << m_file;
|
||||
if(use_line_info && m_row.first > 0) ss << ":" << m_row.first;
|
||||
if(use_file_info && m_file.length() > 0) ss << "]";
|
||||
|
||||
m_signature = ss.str();
|
||||
return m_signature;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fwd.hpp"
|
||||
|
||||
struct function_signature
|
||||
{
|
||||
using location_t = std::pair<unsigned long, unsigned long>;
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(function_signature)
|
||||
|
||||
function_signature(string_t _ret, const string_t& _name, string_t _file,
|
||||
location_t _row = { 0, 0 }, location_t _col = { 0, 0 },
|
||||
bool _loop = false, bool _info_beg = false,
|
||||
bool _info_end = false);
|
||||
|
||||
function_signature(const string_t& _ret, const string_t& _name, const string_t& _file,
|
||||
const std::vector<string_t>& _params, location_t _row = { 0, 0 },
|
||||
location_t _col = { 0, 0 }, bool _loop = false,
|
||||
bool _info_beg = false, bool _info_end = false);
|
||||
|
||||
static string_t get(function_signature& sig);
|
||||
string_t get() const;
|
||||
|
||||
bool m_loop = false;
|
||||
bool m_info_beg = false;
|
||||
bool m_info_end = false;
|
||||
location_t m_row = { 0, 0 };
|
||||
location_t m_col = { 0, 0 };
|
||||
string_t m_return = {};
|
||||
string_t m_name = {};
|
||||
string_t m_params = "()";
|
||||
string_t m_file = {};
|
||||
mutable string_t m_signature = {};
|
||||
|
||||
friend bool operator==(const function_signature& lhs, const function_signature& rhs)
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
template <typename ArchiveT>
|
||||
void serialize(ArchiveT& _ar, const unsigned)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
(void) get();
|
||||
_ar(cereal::make_nvp("loop", m_loop), cereal::make_nvp("info_beg", m_info_beg),
|
||||
cereal::make_nvp("info_end", m_info_end), cereal::make_nvp("row", m_row),
|
||||
cereal::make_nvp("col", m_col), cereal::make_nvp("return", m_return),
|
||||
cereal::make_nvp("name", m_name), cereal::make_nvp("params", m_params),
|
||||
cereal::make_nvp("file", m_file), cereal::make_nvp("signature", m_signature));
|
||||
(void) get();
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,273 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <timemory/backends/process.hpp>
|
||||
#include <timemory/environment.hpp>
|
||||
#include <timemory/mpl/apply.hpp>
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/mpl/policy.hpp>
|
||||
#include <timemory/tpls/cereal/archives.hpp>
|
||||
#include <timemory/tpls/cereal/cereal.hpp>
|
||||
#include <timemory/utility/argparse.hpp>
|
||||
#include <timemory/utility/demangle.hpp>
|
||||
#include <timemory/utility/popen.hpp>
|
||||
#include <timemory/variadic/macros.hpp>
|
||||
|
||||
#include <BPatch.h>
|
||||
#include <BPatch_Vector.h>
|
||||
#include <BPatch_addressSpace.h>
|
||||
#include <BPatch_basicBlock.h>
|
||||
#include <BPatch_basicBlockLoop.h>
|
||||
#include <BPatch_callbacks.h>
|
||||
#include <BPatch_function.h>
|
||||
#include <BPatch_instruction.h>
|
||||
#include <BPatch_point.h>
|
||||
#include <BPatch_process.h>
|
||||
#include <BPatch_snippet.h>
|
||||
#include <BPatch_statement.h>
|
||||
#include <Instruction.h>
|
||||
#include <dyntypes.h>
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <ostream>
|
||||
#include <regex>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#define MUTNAMELEN 1024
|
||||
#define FUNCNAMELEN 32 * 1024
|
||||
#define NO_ERROR -1
|
||||
#define TIMEMORY_BIN_DIR "bin"
|
||||
|
||||
#if !defined(PATH_MAX)
|
||||
# define PATH_MAX std::numeric_limits<int>::max();
|
||||
#endif
|
||||
|
||||
struct function_signature;
|
||||
struct module_function;
|
||||
|
||||
template <typename Tp>
|
||||
using bpvector_t = BPatch_Vector<Tp>;
|
||||
|
||||
using string_t = std::string;
|
||||
using string_view_t = std::string_view;
|
||||
using stringstream_t = std::stringstream;
|
||||
using strvec_t = std::vector<string_t>;
|
||||
using strset_t = std::set<string_t>;
|
||||
using regexvec_t = std::vector<std::regex>;
|
||||
using fmodset_t = std::set<module_function>;
|
||||
using fixed_modset_t = std::map<fmodset_t*, bool>;
|
||||
using exec_callback_t = BPatchExecCallback;
|
||||
using exit_callback_t = BPatchExitCallback;
|
||||
using fork_callback_t = BPatchForkCallback;
|
||||
using patch_t = BPatch;
|
||||
using process_t = BPatch_process;
|
||||
using thread_t = BPatch_thread;
|
||||
using binary_edit_t = BPatch_binaryEdit;
|
||||
using image_t = BPatch_image;
|
||||
using module_t = BPatch_module;
|
||||
using procedure_t = BPatch_function;
|
||||
using snippet_t = BPatch_snippet;
|
||||
using call_expr_t = BPatch_funcCallExpr;
|
||||
using address_space_t = BPatch_addressSpace;
|
||||
using flow_graph_t = BPatch_flowGraph;
|
||||
using basic_block_t = BPatch_basicBlock;
|
||||
using basic_loop_t = BPatch_basicBlockLoop;
|
||||
using procedure_loc_t = BPatch_procedureLocation;
|
||||
using point_t = BPatch_point;
|
||||
using local_var_t = BPatch_localVar;
|
||||
using const_expr_t = BPatch_constExpr;
|
||||
using error_level_t = BPatchErrorLevel;
|
||||
using patch_pointer_t = std::shared_ptr<patch_t>;
|
||||
using snippet_pointer_t = std::shared_ptr<snippet_t>;
|
||||
using call_expr_pointer_t = std::shared_ptr<call_expr_t>;
|
||||
using snippet_vec_t = bpvector_t<snippet_t*>;
|
||||
using procedure_vec_t = bpvector_t<procedure_t*>;
|
||||
using basic_block_set_t = std::set<basic_block_t*>;
|
||||
using basic_loop_vec_t = bpvector_t<basic_loop_t*>;
|
||||
using snippet_pointer_vec_t = std::vector<snippet_pointer_t>;
|
||||
using instruction_t = Dyninst::InstructionAPI::Instruction;
|
||||
|
||||
void
|
||||
omnitrace_prefork_callback(thread_t* parent, thread_t* child);
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
// label settings
|
||||
//
|
||||
extern bool use_return_info;
|
||||
extern bool use_args_info;
|
||||
extern bool use_file_info;
|
||||
extern bool use_line_info;
|
||||
//
|
||||
// heuristic settings
|
||||
//
|
||||
extern bool allow_overlapping;
|
||||
extern bool loop_level_instr;
|
||||
extern bool instr_dynamic_callsites;
|
||||
extern bool instr_traps;
|
||||
extern bool instr_loop_traps;
|
||||
extern size_t min_address_range;
|
||||
extern size_t min_loop_address_range;
|
||||
extern size_t min_instructions;
|
||||
//
|
||||
// debug settings
|
||||
//
|
||||
extern bool werror;
|
||||
extern bool debug_print;
|
||||
extern int verbose_level;
|
||||
//
|
||||
// string settings
|
||||
//
|
||||
extern string_t main_fname;
|
||||
extern string_t argv0;
|
||||
extern string_t cmdv0;
|
||||
extern string_t default_components;
|
||||
extern string_t prefer_library;
|
||||
//
|
||||
// global variables
|
||||
//
|
||||
extern patch_pointer_t bpatch;
|
||||
extern call_expr_t* terminate_expr;
|
||||
extern snippet_vec_t init_names;
|
||||
extern snippet_vec_t fini_names;
|
||||
extern fmodset_t available_module_functions;
|
||||
extern fmodset_t instrumented_module_functions;
|
||||
extern fmodset_t overlapping_module_functions;
|
||||
extern fmodset_t excluded_module_functions;
|
||||
extern fixed_modset_t fixed_module_functions;
|
||||
extern regexvec_t func_include;
|
||||
extern regexvec_t func_exclude;
|
||||
extern regexvec_t file_include;
|
||||
extern regexvec_t file_exclude;
|
||||
extern regexvec_t file_restrict;
|
||||
extern regexvec_t func_restrict;
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
// control debug printf statements
|
||||
#define errprintf(LEVEL, ...) \
|
||||
{ \
|
||||
if(werror || LEVEL < 0) \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) \
|
||||
fprintf(stderr, "[omnitrace][exe] Error! " __VA_ARGS__); \
|
||||
char _buff[FUNCNAMELEN]; \
|
||||
sprintf(_buff, "[omnitrace][exe] Error! " __VA_ARGS__); \
|
||||
throw std::runtime_error(std::string{ _buff }); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) \
|
||||
fprintf(stderr, "[omnitrace][exe] Warning! " __VA_ARGS__); \
|
||||
} \
|
||||
fflush(stderr); \
|
||||
}
|
||||
|
||||
// control verbose printf statements
|
||||
#define verbprintf(LEVEL, ...) \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) \
|
||||
fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
#define verbprintf_bare(LEVEL, ...) \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
template <typename... T>
|
||||
void
|
||||
consume_parameters(T&&...)
|
||||
{}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
extern "C"
|
||||
{
|
||||
bool are_file_include_exclude_lists_empty();
|
||||
bool instrument_module(const string_t& file_name);
|
||||
bool instrument_entity(const string_t& function_name);
|
||||
bool module_constraint(string_view_t fname);
|
||||
bool routine_constraint(string_view_t fname);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
strset_t
|
||||
get_whole_function_names();
|
||||
|
||||
function_signature
|
||||
get_func_file_line_info(module_t* mutatee_module, procedure_t* f);
|
||||
|
||||
function_signature
|
||||
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
|
||||
basic_loop_t* loopToInstrument);
|
||||
|
||||
std::tuple<size_t, size_t>
|
||||
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc,
|
||||
flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr);
|
||||
|
||||
bool
|
||||
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc, flow_graph_t* cfGraph,
|
||||
basic_loop_t* loopToInstrument, bool allow_traps);
|
||||
|
||||
template <typename Tp>
|
||||
bool
|
||||
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
|
||||
procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr,
|
||||
basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true);
|
||||
|
||||
void
|
||||
errorFunc(error_level_t level, int num, const char** params);
|
||||
|
||||
procedure_t*
|
||||
find_function(image_t* appImage, const string_t& functionName, const strset_t& = {});
|
||||
|
||||
void
|
||||
error_func_real(error_level_t level, int num, const char* const* params);
|
||||
|
||||
void
|
||||
error_func_fake(error_level_t level, int num, const char* const* params);
|
||||
@@ -0,0 +1,251 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "fwd.hpp"
|
||||
#include "module_function.hpp"
|
||||
|
||||
static inline void
|
||||
dump_info(std::ostream& _os, const fmodset_t& _data)
|
||||
{
|
||||
module_function::reset_width();
|
||||
for(const auto& itr : _data)
|
||||
module_function::update_width(itr);
|
||||
|
||||
module_function::write_header(_os);
|
||||
for(const auto& itr : _data)
|
||||
_os << itr << '\n';
|
||||
|
||||
module_function::reset_width();
|
||||
}
|
||||
//
|
||||
template <typename ArchiveT,
|
||||
std::enable_if_t<tim::concepts::is_archive<ArchiveT>::value, int> = 0>
|
||||
static inline void
|
||||
dump_info(ArchiveT& _ar, const fmodset_t& _data)
|
||||
{
|
||||
_ar(tim::cereal::make_nvp("module_functions", _data));
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
dump_info(const string_t& _label, string_t _oname, const string_t& _ext,
|
||||
const fmodset_t& _data, int _level, bool _fail)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
namespace policy = tim::policy;
|
||||
|
||||
_oname += "." + _ext;
|
||||
auto _handle_error = [&]() {
|
||||
std::stringstream _msg{};
|
||||
_msg << "[dump_info] Error opening '" << _oname << " for output";
|
||||
verbprintf(_level, "%s\n", _msg.str().c_str());
|
||||
if(_fail)
|
||||
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
|
||||
};
|
||||
|
||||
if(!debug_print && verbose_level < _level) return;
|
||||
|
||||
if(_ext == "txt")
|
||||
{
|
||||
std::ofstream ofs{};
|
||||
if(!tim::filepath::open(ofs, _oname))
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
|
||||
dump_info(ofs, _data);
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
else if(_ext == "xml")
|
||||
{
|
||||
std::stringstream oss{};
|
||||
{
|
||||
using output_policy = policy::output_archive<cereal::XMLOutputArchive>;
|
||||
output_policy::indent() = true;
|
||||
auto ar = output_policy::get(oss);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
|
||||
std::ofstream ofs{};
|
||||
if(!tim::filepath::open(ofs, _oname))
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
|
||||
ofs << oss.str() << std::endl;
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
else if(_ext == "json")
|
||||
{
|
||||
std::stringstream oss{};
|
||||
{
|
||||
using output_policy = policy::output_archive<cereal::PrettyJSONOutputArchive>;
|
||||
auto ar = output_policy::get(oss);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
|
||||
std::ofstream ofs{};
|
||||
if(!tim::filepath::open(ofs, _oname))
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
|
||||
ofs << oss.str() << std::endl;
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(TIMEMORY_JOIN(
|
||||
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _oname,
|
||||
"' does not have one of recognized file extensions: txt, json, xml"));
|
||||
}
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
dump_info(const string_t& _oname, const fmodset_t& _data, int _level, bool _fail,
|
||||
const string_t& _type, const strset_t& _ext)
|
||||
{
|
||||
for(const auto& itr : _ext)
|
||||
dump_info(_type, _oname, itr, _data, _level, _fail);
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
load_info(const string_t& _label, const string_t& _iname, fmodset_t& _data, int _level)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
namespace policy = tim::policy;
|
||||
|
||||
auto _pos = _iname.find_last_of('.');
|
||||
std::string _ext = {};
|
||||
if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1, _iname.length());
|
||||
|
||||
auto _handle_error = [&]() {
|
||||
std::stringstream _msg{};
|
||||
_msg << "[load_info] Error opening '" << _iname << " for input";
|
||||
verbprintf(_level, "%s\n", _msg.str().c_str());
|
||||
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
|
||||
};
|
||||
|
||||
if(_ext == "xml")
|
||||
{
|
||||
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
|
||||
std::ifstream ifs{ _iname };
|
||||
if(!ifs)
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
using input_policy = policy::input_archive<cereal::XMLInputArchive>;
|
||||
auto ar = input_policy::get(ifs);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
ifs.close();
|
||||
}
|
||||
else if(_ext == "json")
|
||||
{
|
||||
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
|
||||
std::ifstream ifs{ _iname };
|
||||
if(!ifs)
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
using input_policy = policy::input_archive<cereal::JSONInputArchive>;
|
||||
auto ar = input_policy::get(ifs);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
ifs.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(TIMEMORY_JOIN(
|
||||
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _iname,
|
||||
"' does not have one of recognized extentions: txt, json, xml :: ", _ext));
|
||||
}
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
load_info(const string_t& _inp, std::map<std::string, fmodset_t*>& _data, int _level)
|
||||
{
|
||||
std::vector<std::string> _exceptions{};
|
||||
_exceptions.reserve(_data.size());
|
||||
for(auto& itr : _data)
|
||||
{
|
||||
try
|
||||
{
|
||||
fmodset_t _tmp{};
|
||||
load_info(itr.first, _inp, _tmp, _level);
|
||||
// add to the existing
|
||||
itr.second->insert(_tmp.begin(), _tmp.end());
|
||||
// if it did not throw it was successfully loaded
|
||||
_exceptions.clear();
|
||||
break;
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
_exceptions.emplace_back(_e.what());
|
||||
}
|
||||
}
|
||||
if(!_exceptions.empty())
|
||||
{
|
||||
std::stringstream _msg{};
|
||||
for(auto& itr : _exceptions)
|
||||
{
|
||||
_msg << "[omnitrace][exe] " << itr << "\n";
|
||||
}
|
||||
throw std::runtime_error(_msg.str());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "module_function.hpp"
|
||||
#include "fwd.hpp"
|
||||
#include "omnitrace.hpp"
|
||||
|
||||
module_function::width_t&
|
||||
module_function::get_width()
|
||||
{
|
||||
static width_t _instance = []() {
|
||||
width_t _tmp;
|
||||
_tmp.fill(0);
|
||||
return _tmp;
|
||||
}();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
void
|
||||
module_function::reset_width()
|
||||
{
|
||||
get_width().fill(0);
|
||||
}
|
||||
|
||||
void
|
||||
module_function::update_width(const module_function& rhs)
|
||||
{
|
||||
get_width()[0] = std::max<size_t>(get_width()[0], rhs.module_name.length());
|
||||
get_width()[1] = std::max<size_t>(get_width()[1], rhs.function_name.length());
|
||||
get_width()[2] = std::max<size_t>(get_width()[2], rhs.signature.get().length());
|
||||
}
|
||||
|
||||
module_function::module_function(module_t* mod, procedure_t* proc)
|
||||
: module{ mod }
|
||||
, function{ proc }
|
||||
, flow_graph{ proc->getCFG() }
|
||||
{
|
||||
if(flow_graph)
|
||||
{
|
||||
flow_graph->getAllBasicBlocks(basic_blocks);
|
||||
flow_graph->getOuterLoops(loop_blocks);
|
||||
}
|
||||
|
||||
for(const auto& itr : basic_blocks)
|
||||
{
|
||||
std::vector<instruction_t> instructions{};
|
||||
itr->getInstructions(instructions);
|
||||
num_instructions += instructions.size();
|
||||
}
|
||||
|
||||
char modname[FUNCNAMELEN];
|
||||
char fname[FUNCNAMELEN];
|
||||
module->getFullName(modname, FUNCNAMELEN);
|
||||
function->getName(fname, FUNCNAMELEN);
|
||||
module_name = modname;
|
||||
function_name = fname;
|
||||
signature = get_func_file_line_info(module, function);
|
||||
|
||||
if(!function->isInstrumentable())
|
||||
{
|
||||
verbprintf(0,
|
||||
"Warning! module function generated for un-instrumentable "
|
||||
"function: %s [%s]\n",
|
||||
function_name.c_str(), module_name.c_str());
|
||||
}
|
||||
std::pair<address_t, address_t> _range{};
|
||||
if(function->getAddressRange(_range.first, _range.second))
|
||||
address_range = _range.second - _range.first;
|
||||
}
|
||||
|
||||
void
|
||||
module_function::write_header(std::ostream& os)
|
||||
{
|
||||
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
|
||||
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
|
||||
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::setw(14) << "AddressRange"
|
||||
<< " " << std::setw(14) << "#Instructions"
|
||||
<< " " << std::setw(6) << "Ratio"
|
||||
<< " " << std::setw(w0 + 8) << std::left << "Module"
|
||||
<< " " << std::setw(w1 + 8) << std::left << "Function"
|
||||
<< " " << std::setw(w2 + 8) << std::left << "FunctionSignature"
|
||||
<< "\n";
|
||||
os << ss.str();
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::should_instrument() const
|
||||
{
|
||||
// hard constraints
|
||||
if(!is_instrumentable()) return false;
|
||||
if(!can_instrument_entry()) return false;
|
||||
if(!can_instrument_exit()) return false;
|
||||
if(is_module_constrained()) return false;
|
||||
if(is_routine_constrained()) return false;
|
||||
|
||||
// should be before user selection
|
||||
constexpr int absolute_min_instructions = 4;
|
||||
if(num_instructions < absolute_min_instructions)
|
||||
{
|
||||
messages.emplace_back(
|
||||
2, "Skipping", "function",
|
||||
TIMEMORY_JOIN("-", "less-than", absolute_min_instructions, "instructions"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// user selection
|
||||
if(is_user_excluded()) return false;
|
||||
if(is_user_restricted()) return true;
|
||||
if(is_user_included()) return true;
|
||||
|
||||
// should be applied before dynamic-callsite check
|
||||
if(is_overlapping_constrained()) return false;
|
||||
if(is_entry_trap_constrained()) return false;
|
||||
if(is_exit_trap_constrained()) return false;
|
||||
|
||||
// needs to be applied before address range and number of instruction constraints
|
||||
if(is_dynamic_callsite_forced()) return true;
|
||||
|
||||
if(is_address_range_constrained()) return false;
|
||||
if(is_num_instructions_constrained()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_instrumentable() const
|
||||
{
|
||||
if(!function->isInstrumentable())
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "module", "not-instrumentable");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
bool
|
||||
check_regex_restrictions(const std::string& _name, const regexvec_t& _regexes)
|
||||
{
|
||||
// NOLINTNEXTLINE
|
||||
for(auto& itr : _regexes)
|
||||
if(std::regex_search(_name, itr)) return true;
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
module_function::is_user_restricted() const
|
||||
{
|
||||
if(!file_restrict.empty())
|
||||
{
|
||||
if(check_regex_restrictions(module_name, file_restrict))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "module", "module-restrict-regex");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "module", "module-restrict-regex");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!func_restrict.empty())
|
||||
{
|
||||
if(check_regex_restrictions(module_name, func_restrict))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
|
||||
return false;
|
||||
}
|
||||
else if(check_regex_restrictions(signature.get(), func_restrict))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-restrict-regex");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", "function-restrict-regex");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_user_included() const
|
||||
{
|
||||
if(!file_include.empty())
|
||||
{
|
||||
if(check_regex_restrictions(module_name, file_include))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "module", "module-include-regex");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!func_include.empty())
|
||||
{
|
||||
if(check_regex_restrictions(function_name, func_include))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
|
||||
return true;
|
||||
}
|
||||
else if(check_regex_restrictions(signature.get(), func_include))
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "function-include-regex");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_user_excluded() const
|
||||
{
|
||||
if(!file_exclude.empty())
|
||||
{
|
||||
if(check_regex_restrictions(module_name, file_exclude))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "module", "module-exclude-regex");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!func_exclude.empty())
|
||||
{
|
||||
if(check_regex_restrictions(function_name, func_exclude))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
|
||||
return true;
|
||||
}
|
||||
else if(check_regex_restrictions(signature.get(), func_exclude))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "function-exclude-regex");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_overlapping() const
|
||||
{
|
||||
procedure_vec_t _overlapping{};
|
||||
return function->findOverlapping(_overlapping);
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_module_constrained() const
|
||||
{
|
||||
if(!instrument_module(module_name) || module_constraint(module_name.c_str()))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "module", "module-constraint");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_routine_constrained() const
|
||||
{
|
||||
if(!instrument_entity(function_name) || !instrument_entity(signature.get()) ||
|
||||
routine_constraint(function_name) || routine_constraint(signature.get()))
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "function-constraint");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_overlapping_constrained() const
|
||||
{
|
||||
if(!allow_overlapping && is_overlapping())
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "overlapping");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::contains_dynamic_callsites() const
|
||||
{
|
||||
if(flow_graph) return flow_graph->containsDynamicCallsites();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_dynamic_callsite_forced() const
|
||||
{
|
||||
if(instr_dynamic_callsites && contains_dynamic_callsites())
|
||||
{
|
||||
messages.emplace_back(2, "Forcing", "function", "dynamic-callsites");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_address_range_constrained() const
|
||||
{
|
||||
if(!loop_blocks.empty()) return is_loop_address_range_constrained();
|
||||
|
||||
if(address_range < min_address_range)
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "min-address-range");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_loop_address_range_constrained() const
|
||||
{
|
||||
if(loop_blocks.empty()) return false;
|
||||
|
||||
if(address_range < min_loop_address_range)
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "min-address-range-loop");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_num_instructions_constrained() const
|
||||
{
|
||||
if(num_instructions < min_instructions)
|
||||
{
|
||||
messages.emplace_back(2, "Skipping", "function", "min-instructions");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::can_instrument_entry() const
|
||||
{
|
||||
size_t _num_points = 0;
|
||||
size_t _num_traps = 0;
|
||||
|
||||
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_entry);
|
||||
|
||||
if(_num_points == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-entry-point");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::can_instrument_exit() const
|
||||
{
|
||||
size_t _num_points = 0;
|
||||
size_t _num_traps = 0;
|
||||
|
||||
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_exit);
|
||||
|
||||
if(_num_points == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", "no-instrumentable-exit-point");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_entry_trap_constrained() const
|
||||
{
|
||||
if(instr_traps) return false;
|
||||
|
||||
size_t _num_points = 0;
|
||||
size_t _num_traps = 0;
|
||||
|
||||
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_entry);
|
||||
|
||||
if(!instr_traps && (_num_points - _num_traps) == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function",
|
||||
"entry-point-trap-instrumentation");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
module_function::is_exit_trap_constrained() const
|
||||
{
|
||||
if(instr_traps) return false;
|
||||
|
||||
size_t _num_points = 0;
|
||||
size_t _num_traps = 0;
|
||||
|
||||
std::tie(_num_points, _num_traps) = query_instr(function, BPatch_exit);
|
||||
|
||||
if((_num_points - _num_traps) == 0)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function",
|
||||
"exit-point-trap-instrumentation");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::pair<size_t, size_t>
|
||||
module_function::operator()(address_space_t* _addr_space, procedure_t* _entr_trace,
|
||||
procedure_t* _exit_trace) const
|
||||
{
|
||||
std::pair<size_t, size_t> _count = { 0, 0 };
|
||||
|
||||
auto _name = signature.get();
|
||||
auto _trace_entr = omnitrace_call_expr(_name.c_str());
|
||||
auto _trace_exit = omnitrace_call_expr(_name.c_str());
|
||||
auto _entr = _trace_entr.get(_entr_trace);
|
||||
auto _exit = _trace_exit.get(_exit_trace);
|
||||
|
||||
if(insert_instr(_addr_space, function, _entr, BPatch_entry, nullptr, nullptr,
|
||||
instr_traps) &&
|
||||
insert_instr(_addr_space, function, _exit, BPatch_exit, nullptr, nullptr,
|
||||
instr_traps))
|
||||
{
|
||||
messages.emplace_back(1, "Instrumenting", "function", "no-constraint");
|
||||
++_count.first;
|
||||
}
|
||||
|
||||
for(auto* itr : loop_blocks)
|
||||
{
|
||||
if(!loop_level_instr) continue;
|
||||
|
||||
auto _is_constrained = [this](bool _v, const std::string& _label) {
|
||||
if(!_v)
|
||||
{
|
||||
messages.emplace_back(3, "Skipping", "function", _label);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
size_t _points = 0;
|
||||
size_t _ntraps = 0;
|
||||
std::tie(_points, _ntraps) = query_instr(function, BPatch_entry, flow_graph, itr);
|
||||
|
||||
if(_is_constrained(_points == 0, "no-instrumentable-loop-entry-point")) continue;
|
||||
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
|
||||
"loop-entry-point-trap-instrumentation"))
|
||||
continue;
|
||||
|
||||
std::tie(_points, _ntraps) = query_instr(function, BPatch_exit, flow_graph, itr);
|
||||
|
||||
if(_is_constrained(_points == 0, "no-instrumentable-loop-exit-point")) continue;
|
||||
if(_is_constrained(!instr_traps && (_points - _ntraps) == 0,
|
||||
"loop-exit-point-trap-instrumentation"))
|
||||
continue;
|
||||
|
||||
auto lname = get_loop_file_line_info(module, function, flow_graph, itr);
|
||||
auto _lname = lname.get();
|
||||
|
||||
messages.emplace_back(1, "Loop Instrumenting", "function", "no-constraint");
|
||||
++_count.second;
|
||||
|
||||
auto _ltrace_entr = omnitrace_call_expr(_lname.c_str());
|
||||
auto _ltrace_exit = omnitrace_call_expr(_lname.c_str());
|
||||
auto _lentr = _ltrace_entr.get(_entr_trace);
|
||||
auto _lexit = _ltrace_exit.get(_exit_trace);
|
||||
|
||||
insert_instr(_addr_space, function, _lentr, BPatch_entry, flow_graph, itr,
|
||||
instr_loop_traps);
|
||||
insert_instr(_addr_space, function, _lexit, BPatch_exit, flow_graph, itr,
|
||||
instr_loop_traps);
|
||||
}
|
||||
|
||||
return _count;
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "function_signature.hpp"
|
||||
#include "fwd.hpp"
|
||||
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/tpls/cereal/cereal/cereal.hpp>
|
||||
|
||||
struct module_function
|
||||
{
|
||||
using width_t = std::array<size_t, 4>;
|
||||
using address_t = Dyninst::Address;
|
||||
|
||||
static constexpr size_t absolute_max_width = 80;
|
||||
static width_t& get_width();
|
||||
static void reset_width();
|
||||
static void update_width(const module_function& rhs);
|
||||
static void write_header(std::ostream& os);
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(module_function)
|
||||
|
||||
module_function(module_t* mod, procedure_t* proc);
|
||||
|
||||
std::pair<size_t, size_t> operator()(address_space_t* _addr_space,
|
||||
procedure_t* _entr_trace,
|
||||
procedure_t* _exit_trace) const;
|
||||
|
||||
// applies logic for all "is_*" and "can_*" checks below
|
||||
bool should_instrument() const;
|
||||
|
||||
// hard constraints
|
||||
bool is_instrumentable() const; // checks whether can instrument
|
||||
bool can_instrument_entry() const; // checks for entry points
|
||||
bool can_instrument_exit() const; // checks for exit points
|
||||
bool is_module_constrained() const; // checks module constraints
|
||||
bool is_routine_constrained() const; // checks function constraints
|
||||
|
||||
// user bypass of heuristics
|
||||
bool is_user_restricted() const; // checks user restrict regexes
|
||||
bool is_user_included() const; // checks user include regexes
|
||||
bool is_user_excluded() const; // checks user exclude regexes
|
||||
|
||||
// applied before dynamic-callsite constraint
|
||||
bool is_overlapping_constrained() const; // checks overlapping constrains
|
||||
bool is_entry_trap_constrained() const; // checks entry trap constraint
|
||||
bool is_exit_trap_constrained() const; // checks exit trap constraint
|
||||
|
||||
// applied before address range and # instruction constraints
|
||||
bool is_dynamic_callsite_forced() const; // checks dynamic callsites
|
||||
|
||||
// estimate the size/work of the function
|
||||
bool is_address_range_constrained() const; // checks address range constraint
|
||||
bool is_num_instructions_constrained() const; // check # instructions constraint
|
||||
|
||||
uint64_t address_range = 0;
|
||||
uint64_t num_instructions = 0;
|
||||
module_t* module = nullptr;
|
||||
procedure_t* function = nullptr;
|
||||
flow_graph_t* flow_graph = nullptr;
|
||||
string_t module_name = {};
|
||||
string_t function_name = {};
|
||||
function_signature signature = {};
|
||||
basic_block_set_t basic_blocks = {};
|
||||
basic_loop_vec_t loop_blocks = {};
|
||||
|
||||
using str_msg_t = std::tuple<int, string_t, string_t, string_t>;
|
||||
using str_msg_vec_t = std::vector<str_msg_t>;
|
||||
|
||||
mutable str_msg_vec_t messages = {};
|
||||
|
||||
bool is_overlapping() const; // checks if func overlaps
|
||||
|
||||
private:
|
||||
bool is_loop_address_range_constrained() const; // checks loop addr range constraint
|
||||
bool contains_dynamic_callsites() const;
|
||||
|
||||
public:
|
||||
template <typename ArchiveT>
|
||||
void serialize(ArchiveT& ar, const unsigned);
|
||||
|
||||
friend bool operator<(const module_function& lhs, const module_function& rhs)
|
||||
{
|
||||
return (lhs.module_name == rhs.module_name)
|
||||
? ((lhs.function_name == rhs.function_name)
|
||||
? (lhs.signature.get() < rhs.signature.get())
|
||||
: (lhs.function_name < rhs.function_name))
|
||||
: (lhs.module_name < rhs.module_name);
|
||||
}
|
||||
|
||||
friend bool operator==(const module_function& lhs, const module_function& rhs)
|
||||
{
|
||||
return std::tie(lhs.module_name, lhs.function_name, lhs.signature,
|
||||
lhs.address_range, lhs.num_instructions) ==
|
||||
std::tie(rhs.module_name, rhs.function_name, rhs.signature,
|
||||
rhs.address_range, rhs.num_instructions);
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const module_function& rhs)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
|
||||
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
|
||||
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
|
||||
|
||||
auto _get_str = [](const std::string& _inc) {
|
||||
if(_inc.length() > absolute_max_width)
|
||||
return _inc.substr(0, absolute_max_width - 3) + "...";
|
||||
return _inc;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
ss << std::setw(14) << rhs.address_range << " "
|
||||
<< std::setw(14) << rhs.num_instructions << " "
|
||||
<< std::setw(6) << std::setprecision(2) << std::fixed << (rhs.address_range / static_cast<double>(rhs.num_instructions)) << " "
|
||||
<< std::setw(w0 + 8) << std::left << _get_str(rhs.module_name) << " "
|
||||
<< std::setw(w1 + 8) << std::left << _get_str(rhs.function_name) << " "
|
||||
<< std::setw(w2 + 8) << std::left << _get_str(rhs.signature.get());
|
||||
// clang-format on
|
||||
|
||||
os << ss.str();
|
||||
return os;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ArchiveT>
|
||||
void
|
||||
module_function::serialize(ArchiveT& ar, const unsigned)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
ar(cereal::make_nvp("address_range", address_range),
|
||||
cereal::make_nvp("instructions", num_instructions),
|
||||
cereal::make_nvp("module", module_name),
|
||||
cereal::make_nvp("function", function_name),
|
||||
cereal::make_nvp("signature", signature));
|
||||
|
||||
if constexpr(tim::concepts::is_output_archive<ArchiveT>::value)
|
||||
{
|
||||
ar.setNextName("heuristics");
|
||||
ar.startNode();
|
||||
ar(cereal::make_nvp("should_instrument", should_instrument()),
|
||||
cereal::make_nvp("is_instrumentable", is_instrumentable()),
|
||||
cereal::make_nvp("can_instrument_entry", can_instrument_entry()),
|
||||
cereal::make_nvp("can_instrument_exit", can_instrument_exit()),
|
||||
cereal::make_nvp("contains_dynamic_callsites", contains_dynamic_callsites()),
|
||||
cereal::make_nvp("is_module_constrained", is_module_constrained()),
|
||||
cereal::make_nvp("is_routine_constrained", is_routine_constrained()),
|
||||
cereal::make_nvp("is_user_restricted", is_user_restricted()),
|
||||
cereal::make_nvp("is_user_included", is_user_included()),
|
||||
cereal::make_nvp("is_user_excluded", is_user_excluded()),
|
||||
cereal::make_nvp("is_overlapping_constrained", is_overlapping_constrained()),
|
||||
cereal::make_nvp("is_entry_trap_constrained", is_entry_trap_constrained()),
|
||||
cereal::make_nvp("is_exit_trap_constrained", is_exit_trap_constrained()),
|
||||
cereal::make_nvp("is_dynamic_callsite_forced", is_dynamic_callsite_forced()),
|
||||
cereal::make_nvp("is_address_range_constrained",
|
||||
is_address_range_constrained()),
|
||||
cereal::make_nvp("is_loop_address_range_constrained",
|
||||
is_loop_address_range_constrained()),
|
||||
cereal::make_nvp("is_num_instructions_constrained",
|
||||
is_num_instructions_constrained()));
|
||||
ar.finishNode();
|
||||
}
|
||||
}
|
||||
Fichier diff supprimé car celui-ci est trop grand
Voir la Diff
@@ -22,231 +22,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <timemory/backends/process.hpp>
|
||||
#include <timemory/environment.hpp>
|
||||
#include <timemory/mpl/apply.hpp>
|
||||
#include <timemory/mpl/concepts.hpp>
|
||||
#include <timemory/mpl/policy.hpp>
|
||||
#include <timemory/tpls/cereal/archives.hpp>
|
||||
#include <timemory/tpls/cereal/cereal.hpp>
|
||||
#include <timemory/utility/argparse.hpp>
|
||||
#include <timemory/utility/demangle.hpp>
|
||||
#include <timemory/utility/popen.hpp>
|
||||
#include <timemory/variadic/macros.hpp>
|
||||
|
||||
#include <BPatch.h>
|
||||
#include <BPatch_Vector.h>
|
||||
#include <BPatch_addressSpace.h>
|
||||
#include <BPatch_basicBlockLoop.h>
|
||||
#include <BPatch_callbacks.h>
|
||||
#include <BPatch_function.h>
|
||||
#include <BPatch_point.h>
|
||||
#include <BPatch_process.h>
|
||||
#include <BPatch_snippet.h>
|
||||
#include <BPatch_statement.h>
|
||||
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <fstream>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <ostream>
|
||||
#include <regex>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
#define MUTNAMELEN 1024
|
||||
#define FUNCNAMELEN 32 * 1024
|
||||
#define NO_ERROR -1
|
||||
#define TIMEMORY_BIN_DIR "bin"
|
||||
|
||||
#if !defined(PATH_MAX)
|
||||
# define PATH_MAX std::numeric_limits<int>::max();
|
||||
#endif
|
||||
|
||||
struct function_signature;
|
||||
struct module_function;
|
||||
|
||||
template <typename Tp>
|
||||
using bpvector_t = BPatch_Vector<Tp>;
|
||||
|
||||
using string_t = std::string;
|
||||
using stringstream_t = std::stringstream;
|
||||
using strvec_t = std::vector<string_t>;
|
||||
using strset_t = std::set<string_t>;
|
||||
using regexvec_t = std::vector<std::regex>;
|
||||
using fmodset_t = std::set<module_function>;
|
||||
using fixed_modset_t = std::map<fmodset_t*, bool>;
|
||||
using exec_callback_t = BPatchExecCallback;
|
||||
using exit_callback_t = BPatchExitCallback;
|
||||
using fork_callback_t = BPatchForkCallback;
|
||||
using patch_t = BPatch;
|
||||
using process_t = BPatch_process;
|
||||
using thread_t = BPatch_thread;
|
||||
using binary_edit_t = BPatch_binaryEdit;
|
||||
using image_t = BPatch_image;
|
||||
using module_t = BPatch_module;
|
||||
using procedure_t = BPatch_function;
|
||||
using snippet_t = BPatch_snippet;
|
||||
using call_expr_t = BPatch_funcCallExpr;
|
||||
using address_space_t = BPatch_addressSpace;
|
||||
using flow_graph_t = BPatch_flowGraph;
|
||||
using basic_loop_t = BPatch_basicBlockLoop;
|
||||
using procedure_loc_t = BPatch_procedureLocation;
|
||||
using point_t = BPatch_point;
|
||||
using local_var_t = BPatch_localVar;
|
||||
using const_expr_t = BPatch_constExpr;
|
||||
using error_level_t = BPatchErrorLevel;
|
||||
using patch_pointer_t = std::shared_ptr<patch_t>;
|
||||
using snippet_pointer_t = std::shared_ptr<snippet_t>;
|
||||
using call_expr_pointer_t = std::shared_ptr<call_expr_t>;
|
||||
using snippet_vec_t = bpvector_t<snippet_t*>;
|
||||
using procedure_vec_t = bpvector_t<procedure_t*>;
|
||||
using basic_loop_vec_t = bpvector_t<basic_loop_t*>;
|
||||
using snippet_pointer_vec_t = std::vector<snippet_pointer_t>;
|
||||
|
||||
void
|
||||
omnitrace_prefork_callback(thread_t* parent, thread_t* child);
|
||||
|
||||
//======================================================================================//
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
// boolean settings
|
||||
//
|
||||
static bool use_return_info = false;
|
||||
static bool use_args_info = false;
|
||||
static bool use_file_info = false;
|
||||
static bool use_line_info = false;
|
||||
//
|
||||
// integral settings
|
||||
//
|
||||
extern bool debug_print;
|
||||
extern int verbose_level;
|
||||
//
|
||||
// string settings
|
||||
//
|
||||
static string_t main_fname = "main";
|
||||
static string_t argv0 = {};
|
||||
static string_t cmdv0 = {};
|
||||
static string_t default_components = "wall_clock";
|
||||
static string_t prefer_library = {};
|
||||
//
|
||||
// global variables
|
||||
//
|
||||
static patch_pointer_t bpatch = {};
|
||||
static call_expr_t* terminate_expr = nullptr;
|
||||
static snippet_vec_t init_names = {};
|
||||
static snippet_vec_t fini_names = {};
|
||||
static fmodset_t available_module_functions = {};
|
||||
static fmodset_t instrumented_module_functions = {};
|
||||
static fmodset_t overlapping_module_functions = {};
|
||||
static fmodset_t excluded_module_functions = {};
|
||||
static fixed_modset_t fixed_module_functions = {};
|
||||
static regexvec_t func_include = {};
|
||||
static regexvec_t func_exclude = {};
|
||||
static regexvec_t file_include = {};
|
||||
static regexvec_t file_exclude = {};
|
||||
static regexvec_t file_restrict = {};
|
||||
static regexvec_t func_restrict = {};
|
||||
//
|
||||
//======================================================================================//
|
||||
|
||||
// control debug printf statements
|
||||
#define errprintf(LEVEL, ...) \
|
||||
{ \
|
||||
if(werror || LEVEL < 0) \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) \
|
||||
fprintf(stderr, "[omnitrace][exe] Error! " __VA_ARGS__); \
|
||||
char _buff[FUNCNAMELEN]; \
|
||||
sprintf(_buff, "[omnitrace][exe] Error! " __VA_ARGS__); \
|
||||
throw std::runtime_error(std::string{ _buff }); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) \
|
||||
fprintf(stderr, "[omnitrace][exe] Warning! " __VA_ARGS__); \
|
||||
} \
|
||||
fflush(stderr); \
|
||||
}
|
||||
|
||||
// control verbose printf statements
|
||||
#define verbprintf(LEVEL, ...) \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) \
|
||||
fprintf(stdout, "[omnitrace][exe] " __VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
#define verbprintf_bare(LEVEL, ...) \
|
||||
{ \
|
||||
if(debug_print || verbose_level >= LEVEL) fprintf(stdout, __VA_ARGS__); \
|
||||
fflush(stdout); \
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
template <typename... T>
|
||||
void
|
||||
consume_parameters(T&&...)
|
||||
{}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
extern "C"
|
||||
{
|
||||
bool are_file_include_exclude_lists_empty();
|
||||
bool instrument_module(const string_t& file_name);
|
||||
bool instrument_entity(const string_t& function_name);
|
||||
bool module_constraint(char* fname);
|
||||
bool routine_constraint(const char* fname);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
strset_t
|
||||
get_whole_function_names();
|
||||
|
||||
function_signature
|
||||
get_func_file_line_info(module_t* mutatee_module, procedure_t* f);
|
||||
|
||||
function_signature
|
||||
get_loop_file_line_info(module_t* mutatee_module, procedure_t* f, flow_graph_t* cfGraph,
|
||||
basic_loop_t* loopToInstrument);
|
||||
|
||||
bool
|
||||
query_instr(procedure_t* funcToInstr, procedure_loc_t traceLoc,
|
||||
flow_graph_t* cfGraph = nullptr, basic_loop_t* loopToInstrument = nullptr,
|
||||
bool allow_traps = true);
|
||||
|
||||
template <typename Tp>
|
||||
bool
|
||||
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
|
||||
procedure_loc_t traceLoc, flow_graph_t* cfGraph = nullptr,
|
||||
basic_loop_t* loopToInstrument = nullptr, bool allow_traps = true);
|
||||
|
||||
void
|
||||
errorFunc(error_level_t level, int num, const char** params);
|
||||
|
||||
procedure_t*
|
||||
find_function(image_t* appImage, const string_t& functionName, const strset_t& = {});
|
||||
|
||||
void
|
||||
error_func_real(error_level_t level, int num, const char* const* params);
|
||||
|
||||
void
|
||||
error_func_fake(error_level_t level, int num, const char* const* params);
|
||||
#include "function_signature.hpp"
|
||||
#include "fwd.hpp"
|
||||
#include "info.hpp"
|
||||
#include "module_function.hpp"
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
@@ -285,465 +64,6 @@ to_lower(string_t s)
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
struct function_signature
|
||||
{
|
||||
using location_t = std::pair<unsigned long, unsigned long>;
|
||||
|
||||
bool m_loop = false;
|
||||
bool m_info_beg = false;
|
||||
bool m_info_end = false;
|
||||
location_t m_row = { 0, 0 };
|
||||
location_t m_col = { 0, 0 };
|
||||
string_t m_return = {};
|
||||
string_t m_name = {};
|
||||
string_t m_params = "()";
|
||||
string_t m_file = {};
|
||||
mutable string_t m_signature = {};
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(function_signature)
|
||||
|
||||
template <typename ArchiveT>
|
||||
void serialize(ArchiveT& _ar, const unsigned)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
(void) get();
|
||||
_ar(cereal::make_nvp("loop", m_loop), cereal::make_nvp("info_beg", m_info_beg),
|
||||
cereal::make_nvp("info_end", m_info_end), cereal::make_nvp("row", m_row),
|
||||
cereal::make_nvp("col", m_col), cereal::make_nvp("return", m_return),
|
||||
cereal::make_nvp("name", m_name), cereal::make_nvp("params", m_params),
|
||||
cereal::make_nvp("file", m_file), cereal::make_nvp("signature", m_signature));
|
||||
(void) get();
|
||||
}
|
||||
|
||||
function_signature(string_t _ret, const string_t& _name, string_t _file,
|
||||
location_t _row = { 0, 0 }, location_t _col = { 0, 0 },
|
||||
bool _loop = false, bool _info_beg = false, bool _info_end = false)
|
||||
: m_loop(_loop)
|
||||
, m_info_beg(_info_beg)
|
||||
, m_info_end(_info_end)
|
||||
, m_row(std::move(_row))
|
||||
, m_col(std::move(_col))
|
||||
, m_return(std::move(_ret))
|
||||
, m_name(tim::demangle(_name))
|
||||
, m_file(std::move(_file))
|
||||
{
|
||||
if(m_file.find('/') != string_t::npos)
|
||||
m_file = m_file.substr(m_file.find_last_of('/') + 1);
|
||||
}
|
||||
|
||||
function_signature(const string_t& _ret, const string_t& _name, const string_t& _file,
|
||||
const std::vector<string_t>& _params, location_t _row = { 0, 0 },
|
||||
location_t _col = { 0, 0 }, bool _loop = false,
|
||||
bool _info_beg = false, bool _info_end = false)
|
||||
: function_signature(_ret, _name, _file, _row, _col, _loop, _info_beg, _info_end)
|
||||
{
|
||||
m_params = "(";
|
||||
for(const auto& itr : _params)
|
||||
m_params.append(itr + ", ");
|
||||
if(!_params.empty()) m_params = m_params.substr(0, m_params.length() - 2);
|
||||
m_params += ")";
|
||||
}
|
||||
|
||||
friend bool operator==(const function_signature& lhs, const function_signature& rhs)
|
||||
{
|
||||
return lhs.get() == rhs.get();
|
||||
}
|
||||
|
||||
static auto get(function_signature& sig) { return sig.get(); }
|
||||
|
||||
string_t get() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
if(use_return_info && !m_return.empty()) ss << m_return << " ";
|
||||
ss << m_name;
|
||||
if(use_args_info) ss << m_params;
|
||||
if(m_loop && m_info_beg)
|
||||
{
|
||||
if(m_info_end)
|
||||
{
|
||||
ss << " [{" << m_row.first << "," << m_col.first << "}-{" << m_row.second
|
||||
<< "," << m_col.second << "}]";
|
||||
}
|
||||
else
|
||||
{
|
||||
ss << "[{" << m_row.first << "," << m_col.first << "}]";
|
||||
}
|
||||
}
|
||||
if(use_file_info && m_file.length() > 0) ss << " [" << m_file;
|
||||
if(use_line_info && m_row.first > 0) ss << ":" << m_row.first;
|
||||
if(use_file_info && m_file.length() > 0) ss << "]";
|
||||
|
||||
m_signature = ss.str();
|
||||
return m_signature;
|
||||
}
|
||||
};
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
struct module_function
|
||||
{
|
||||
using width_t = std::array<size_t, 3>;
|
||||
using address_t = Dyninst::Address;
|
||||
|
||||
static constexpr size_t absolute_max_width = 80;
|
||||
|
||||
static auto& get_width()
|
||||
{
|
||||
static width_t _instance = []() {
|
||||
width_t _tmp;
|
||||
_tmp.fill(0);
|
||||
return _tmp;
|
||||
}();
|
||||
return _instance;
|
||||
}
|
||||
|
||||
TIMEMORY_DEFAULT_OBJECT(module_function)
|
||||
|
||||
static void reset_width() { get_width().fill(0); }
|
||||
|
||||
static void update_width(const module_function& rhs)
|
||||
{
|
||||
get_width()[0] = std::max<size_t>(get_width()[0], rhs.module.length());
|
||||
get_width()[1] = std::max<size_t>(get_width()[1], rhs.function.length());
|
||||
get_width()[2] = std::max<size_t>(get_width()[2], rhs.signature.get().length());
|
||||
}
|
||||
|
||||
module_function(string_t _module, string_t _func, function_signature _sign,
|
||||
procedure_t* proc)
|
||||
: module(std::move(_module))
|
||||
, function(std::move(_func))
|
||||
, signature(std::move(_sign))
|
||||
{
|
||||
if(proc)
|
||||
{
|
||||
std::pair<address_t, address_t> _range{};
|
||||
if(proc->getAddressRange(_range.first, _range.second))
|
||||
address_range = _range.second - _range.first;
|
||||
}
|
||||
}
|
||||
|
||||
module_function(module_t* mod, procedure_t* proc)
|
||||
{
|
||||
char modname[FUNCNAMELEN];
|
||||
char fname[FUNCNAMELEN];
|
||||
|
||||
mod->getFullName(modname, FUNCNAMELEN);
|
||||
proc->getName(fname, FUNCNAMELEN);
|
||||
|
||||
module = modname;
|
||||
function = fname;
|
||||
signature = get_func_file_line_info(mod, proc);
|
||||
if(!proc->isInstrumentable())
|
||||
{
|
||||
verbprintf(0,
|
||||
"Warning! module function generated for un-instrumentable "
|
||||
"function: %s [%s]\n",
|
||||
function.c_str(), module.c_str());
|
||||
}
|
||||
std::pair<address_t, address_t> _range{};
|
||||
if(proc->getAddressRange(_range.first, _range.second))
|
||||
address_range = _range.second - _range.first;
|
||||
}
|
||||
|
||||
friend bool operator<(const module_function& lhs, const module_function& rhs)
|
||||
{
|
||||
return (lhs.module == rhs.module)
|
||||
? ((lhs.function == rhs.function)
|
||||
? (lhs.signature.get() < rhs.signature.get())
|
||||
: (lhs.function < rhs.function))
|
||||
: (lhs.module < rhs.module);
|
||||
}
|
||||
|
||||
friend bool operator==(const module_function& lhs, const module_function& rhs)
|
||||
{
|
||||
return std::tie(lhs.module, lhs.function, lhs.signature, lhs.address_range) ==
|
||||
std::tie(rhs.module, rhs.function, rhs.signature, rhs.address_range);
|
||||
}
|
||||
|
||||
static void write_header(std::ostream& os)
|
||||
{
|
||||
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
|
||||
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
|
||||
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::setw(14) << "AddressRange"
|
||||
<< " " << std::setw(w0 + 8) << std::left << "Module"
|
||||
<< " " << std::setw(w1 + 8) << std::left << "Function"
|
||||
<< " " << std::setw(w2 + 8) << std::left << "FunctionSignature"
|
||||
<< "\n";
|
||||
os << ss.str();
|
||||
}
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const module_function& rhs)
|
||||
{
|
||||
std::stringstream ss;
|
||||
|
||||
auto w0 = std::min<size_t>(get_width()[0], absolute_max_width);
|
||||
auto w1 = std::min<size_t>(get_width()[1], absolute_max_width);
|
||||
auto w2 = std::min<size_t>(get_width()[2], absolute_max_width);
|
||||
|
||||
auto _get_str = [](const std::string& _inc) {
|
||||
if(_inc.length() > absolute_max_width)
|
||||
return _inc.substr(0, absolute_max_width - 3) + "...";
|
||||
return _inc;
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
ss << std::setw(14) << rhs.address_range << " "
|
||||
<< std::setw(w0 + 8) << std::left << _get_str(rhs.module) << " "
|
||||
<< std::setw(w1 + 8) << std::left << _get_str(rhs.function) << " "
|
||||
<< std::setw(w2 + 8) << std::left << _get_str(rhs.signature.get());
|
||||
// clang-format on
|
||||
|
||||
os << ss.str();
|
||||
return os;
|
||||
}
|
||||
|
||||
size_t address_range = 0;
|
||||
string_t module = {};
|
||||
string_t function = {};
|
||||
function_signature signature = {};
|
||||
|
||||
template <typename ArchiveT>
|
||||
void serialize(ArchiveT& _ar, const unsigned)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
_ar(cereal::make_nvp("address_range", address_range),
|
||||
cereal::make_nvp("module", module), cereal::make_nvp("function", function),
|
||||
cereal::make_nvp("signature", signature));
|
||||
}
|
||||
};
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
static inline void
|
||||
dump_info(std::ostream& _os, const fmodset_t& _data)
|
||||
{
|
||||
module_function::reset_width();
|
||||
for(const auto& itr : _data)
|
||||
module_function::update_width(itr);
|
||||
|
||||
module_function::write_header(_os);
|
||||
for(const auto& itr : _data)
|
||||
_os << itr << '\n';
|
||||
|
||||
module_function::reset_width();
|
||||
}
|
||||
//
|
||||
template <typename ArchiveT,
|
||||
std::enable_if_t<tim::concepts::is_archive<ArchiveT>::value, int> = 0>
|
||||
static inline void
|
||||
dump_info(ArchiveT& _ar, const fmodset_t& _data)
|
||||
{
|
||||
_ar(tim::cereal::make_nvp("module_functions", _data));
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
dump_info(const string_t& _label, string_t _oname, const string_t& _ext,
|
||||
const fmodset_t& _data, int _level, bool _fail)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
namespace policy = tim::policy;
|
||||
|
||||
_oname += "." + _ext;
|
||||
auto _handle_error = [&]() {
|
||||
std::stringstream _msg{};
|
||||
_msg << "[dump_info] Error opening '" << _oname << " for output";
|
||||
verbprintf(_level, "%s\n", _msg.str().c_str());
|
||||
if(_fail)
|
||||
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
|
||||
};
|
||||
|
||||
if(!debug_print && verbose_level < _level) return;
|
||||
|
||||
if(_ext == "txt")
|
||||
{
|
||||
std::ofstream ofs{};
|
||||
if(!tim::filepath::open(ofs, _oname))
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
|
||||
dump_info(ofs, _data);
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
else if(_ext == "xml")
|
||||
{
|
||||
std::stringstream oss{};
|
||||
{
|
||||
using output_policy = policy::output_archive<cereal::XMLOutputArchive>;
|
||||
output_policy::indent() = true;
|
||||
auto ar = output_policy::get(oss);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
|
||||
std::ofstream ofs{};
|
||||
if(!tim::filepath::open(ofs, _oname))
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
|
||||
ofs << oss.str() << std::endl;
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
else if(_ext == "json")
|
||||
{
|
||||
std::stringstream oss{};
|
||||
{
|
||||
using output_policy = policy::output_archive<cereal::PrettyJSONOutputArchive>;
|
||||
auto ar = output_policy::get(oss);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
|
||||
std::ofstream ofs{};
|
||||
if(!tim::filepath::open(ofs, _oname))
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
verbprintf(_level, "Outputting '%s'... ", _oname.c_str());
|
||||
ofs << oss.str() << std::endl;
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(TIMEMORY_JOIN(
|
||||
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _oname,
|
||||
"' does not have one of recognized file extensions: txt, json, xml"));
|
||||
}
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
dump_info(const string_t& _oname, const fmodset_t& _data, int _level, bool _fail,
|
||||
const string_t& _type, const strset_t& _ext)
|
||||
{
|
||||
for(const auto& itr : _ext)
|
||||
dump_info(_type, _oname, itr, _data, _level, _fail);
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
load_info(const string_t& _label, const string_t& _iname, fmodset_t& _data, int _level)
|
||||
{
|
||||
namespace cereal = tim::cereal;
|
||||
namespace policy = tim::policy;
|
||||
|
||||
auto _pos = _iname.find_last_of('.');
|
||||
std::string _ext = {};
|
||||
if(_pos != std::string::npos) _ext = _iname.substr(_pos + 1, _iname.length());
|
||||
|
||||
auto _handle_error = [&]() {
|
||||
std::stringstream _msg{};
|
||||
_msg << "[load_info] Error opening '" << _iname << " for input";
|
||||
verbprintf(_level, "%s\n", _msg.str().c_str());
|
||||
throw std::runtime_error(std::string{ "[omnitrace][exe]" } + _msg.str());
|
||||
};
|
||||
|
||||
if(_ext == "xml")
|
||||
{
|
||||
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
|
||||
std::ifstream ifs{ _iname };
|
||||
if(!ifs)
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
using input_policy = policy::input_archive<cereal::XMLInputArchive>;
|
||||
auto ar = input_policy::get(ifs);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
ifs.close();
|
||||
}
|
||||
else if(_ext == "json")
|
||||
{
|
||||
verbprintf(_level, "Reading '%s'... ", _iname.c_str());
|
||||
std::ifstream ifs{ _iname };
|
||||
if(!ifs)
|
||||
_handle_error();
|
||||
else
|
||||
{
|
||||
using input_policy = policy::input_archive<cereal::JSONInputArchive>;
|
||||
auto ar = input_policy::get(ifs);
|
||||
|
||||
ar->setNextName("omnitrace");
|
||||
ar->startNode();
|
||||
ar->setNextName(_label.c_str());
|
||||
ar->startNode();
|
||||
(*ar)(cereal::make_nvp("module_functions", _data));
|
||||
ar->finishNode();
|
||||
ar->finishNode();
|
||||
}
|
||||
verbprintf_bare(_level, "Done\n");
|
||||
ifs.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error(TIMEMORY_JOIN(
|
||||
"", "[omnitrace][exe] Error in ", __FUNCTION__, " :: filename '", _iname,
|
||||
"' does not have one of recognized extentions: txt, json, xml :: ", _ext));
|
||||
}
|
||||
}
|
||||
//
|
||||
static inline void
|
||||
load_info(const string_t& _inp, std::map<std::string, fmodset_t*>& _data, int _level)
|
||||
{
|
||||
std::vector<std::string> _exceptions{};
|
||||
_exceptions.reserve(_data.size());
|
||||
for(auto& itr : _data)
|
||||
{
|
||||
try
|
||||
{
|
||||
fmodset_t _tmp{};
|
||||
load_info(itr.first, _inp, _tmp, _level);
|
||||
// add to the existing
|
||||
itr.second->insert(_tmp.begin(), _tmp.end());
|
||||
// if it did not throw it was successfully loaded
|
||||
_exceptions.clear();
|
||||
break;
|
||||
} catch(std::exception& _e)
|
||||
{
|
||||
_exceptions.emplace_back(_e.what());
|
||||
}
|
||||
}
|
||||
if(!_exceptions.empty())
|
||||
{
|
||||
std::stringstream _msg{};
|
||||
for(auto& itr : _exceptions)
|
||||
{
|
||||
_msg << "[omnitrace][exe] " << itr << "\n";
|
||||
}
|
||||
throw std::runtime_error(_msg.str());
|
||||
}
|
||||
}
|
||||
//
|
||||
//======================================================================================//
|
||||
//
|
||||
template <typename Tp, std::enable_if_t<!std::is_same<Tp, std::string>::value, int> = 0>
|
||||
snippet_pointer_t
|
||||
get_snippet(Tp arg)
|
||||
@@ -962,4 +282,79 @@ omnitrace_fork_callback(thread_t* parent, thread_t* child)
|
||||
}
|
||||
//
|
||||
//======================================================================================//
|
||||
// insert_instr -- generic insert instrumentation function
|
||||
//
|
||||
template <typename Tp>
|
||||
bool
|
||||
insert_instr(address_space_t* mutatee, procedure_t* funcToInstr, Tp traceFunc,
|
||||
procedure_loc_t traceLoc, flow_graph_t* cfGraph,
|
||||
basic_loop_t* loopToInstrument, bool allow_traps)
|
||||
{
|
||||
module_t* module = funcToInstr->getModule();
|
||||
if(!module || !traceFunc) return false;
|
||||
|
||||
bpvector_t<point_t*>* _points = nullptr;
|
||||
auto _trace = traceFunc.get();
|
||||
|
||||
if(cfGraph && loopToInstrument)
|
||||
{
|
||||
if(traceLoc == BPatch_entry)
|
||||
_points = cfGraph->findLoopInstPoints(BPatch_locLoopEntry, loopToInstrument);
|
||||
else if(traceLoc == BPatch_exit)
|
||||
_points = cfGraph->findLoopInstPoints(BPatch_locLoopExit, loopToInstrument);
|
||||
}
|
||||
else
|
||||
{
|
||||
_points = funcToInstr->findPoint(traceLoc);
|
||||
}
|
||||
|
||||
if(_points == nullptr) return false;
|
||||
if(_points->empty()) return false;
|
||||
|
||||
/*if(loop_level_instr)
|
||||
{
|
||||
flow_graph_t* flow = funcToInstr->getCFG();
|
||||
bpvector_t<basic_loop_t*> basicLoop;
|
||||
flow->getOuterLoops(basicLoop);
|
||||
for(auto litr = basicLoop.begin(); litr != basicLoop.end(); ++litr)
|
||||
{
|
||||
bpvector_t<point_t*>* _tmp;
|
||||
if(traceLoc == BPatch_entry)
|
||||
_tmp = cfGraph->findLoopInstPoints(BPatch_locLoopEntry, *litr);
|
||||
else if(traceLoc == BPatch_exit)
|
||||
_tmp = cfGraph->findLoopInstPoints(BPatch_locLoopExit, *litr);
|
||||
if(!_tmp)
|
||||
continue;
|
||||
for(auto& itr : *_tmp)
|
||||
_points->push_back(itr);
|
||||
}
|
||||
}*/
|
||||
|
||||
// verbprintf(0, "Instrumenting |> [ %s ]\n", name.m_name.c_str());
|
||||
|
||||
std::set<point_t*> _traps{};
|
||||
if(!allow_traps)
|
||||
{
|
||||
for(auto& itr : *_points)
|
||||
{
|
||||
if(itr && itr->usesTrap_NP()) _traps.insert(itr);
|
||||
}
|
||||
}
|
||||
|
||||
size_t _n = 0;
|
||||
for(auto& itr : *_points)
|
||||
{
|
||||
if(!itr || _traps.count(itr) > 0)
|
||||
continue;
|
||||
else if(traceLoc == BPatch_entry)
|
||||
mutatee->insertSnippet(*_trace, *itr, BPatch_callBefore, BPatch_firstSnippet);
|
||||
// else if(traceLoc == BPatch_exit)
|
||||
// mutatee->insertSnippet(*_trace, *itr, BPatch_callAfter,
|
||||
// BPatch_firstSnippet);
|
||||
else
|
||||
mutatee->insertSnippet(*_trace, *itr);
|
||||
++_n;
|
||||
}
|
||||
|
||||
return (_n > 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
# adds a ctest for executable
|
||||
function(OMNITRACE_ADD_BIN_TEST)
|
||||
cmake_parse_arguments(
|
||||
TEST
|
||||
"" # options
|
||||
"NAME;TARGET;TIMEOUT;WORKING_DIRECTORY" # single value args
|
||||
"ARGS;ENVIRONMENT;LABELS;PROPERTIES;PASS_REGULAR_EXPRESSION;FAIL_REGULAR_EXPRESSION;SKIP_REGULAR_EXPRESSION;DEPENDS;COMMAND" # multiple
|
||||
# value args
|
||||
${ARGN})
|
||||
|
||||
if(NOT OMNITRACE_DYNINST_API_RT_DIR AND OMNITRACE_DYNINST_API_RT)
|
||||
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
|
||||
DIRECTORY)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_BUILD_DYNINST)
|
||||
set(OMNITRACE_DYNINST_API_RT_DIR
|
||||
"${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI_RT:${PROJECT_BINARY_DIR}/external/dyninst/dyninstAPI"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(NOT TEST_ENVIRONMENT)
|
||||
set(TEST_ENVIRONMENT
|
||||
"OMNITRACE_USE_PERFETTO=ON"
|
||||
"OMNITRACE_USE_TIMEMORY=ON"
|
||||
"OMNITRACE_USE_SAMPLING=ON"
|
||||
"OMNITRACE_TIME_OUTPUT=OFF"
|
||||
"LD_LIBRARY_PATH=${PROJECT_BINARY_DIR}:${OMNITRACE_DYNINST_API_RT_DIR}:$ENV{LD_LIBRARY_PATH}"
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND TEST_ENVIRONMENT "OMNITRACE_CI=ON"
|
||||
"OMNITRACE_OUTPUT_PATH=omnitrace-tests-output"
|
||||
"OMNITRACE_OUTPUT_PREFIX=${TEST_NAME}/")
|
||||
|
||||
if(TEST_COMMAND)
|
||||
add_test(
|
||||
NAME ${TEST_NAME}
|
||||
COMMAND ${TEST_COMMAND} ${TEST_ARGS}
|
||||
WORKING_DIRECTORY ${TEST_WORKING_DIRECTORY})
|
||||
|
||||
set_tests_properties(
|
||||
${TEST_NAME}
|
||||
PROPERTIES ENVIRONMENT
|
||||
"${TEST_ENVIRONMENT}"
|
||||
TIMEOUT
|
||||
${TEST_TIMEOUT}
|
||||
LABELS
|
||||
"omnitrace-bin;${TEST_LABELS}"
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"${TEST_PASS_REGULAR_EXPRESSION}"
|
||||
FAIL_REGULAR_EXPRESSION
|
||||
"${TEST_FAIL_REGULAR_EXPRESSION}"
|
||||
SKIP_REGULAR_EXPRESSION
|
||||
"${TEST_SKIP_REGULAR_EXPRESSION}"
|
||||
${TEST_PROPERTIES})
|
||||
elseif(TARGET ${TEST_TARGET})
|
||||
add_test(
|
||||
NAME ${TEST_NAME}
|
||||
COMMAND $<TARGET_FILE:${TEST_TARGET}> ${TEST_ARGS}
|
||||
WORKING_DIRECTORY $<TARGET_FILE_DIR:${TEST_TARGET}>)
|
||||
|
||||
set_tests_properties(
|
||||
${TEST_NAME}
|
||||
PROPERTIES ENVIRONMENT
|
||||
"${TEST_ENVIRONMENT}"
|
||||
TIMEOUT
|
||||
${TEST_TIMEOUT}
|
||||
LABELS
|
||||
"omnitrace-bin;${TEST_LABELS}"
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"${TEST_PASS_REGULAR_EXPRESSION}"
|
||||
FAIL_REGULAR_EXPRESSION
|
||||
"${TEST_FAIL_REGULAR_EXPRESSION}"
|
||||
SKIP_REGULAR_EXPRESSION
|
||||
"${TEST_SKIP_REGULAR_EXPRESSION}"
|
||||
${TEST_PROPERTIES})
|
||||
elseif(OMNITRACE_BUILD_TESTING)
|
||||
message(FATAL_ERROR "Error! ${TEST_TARGET} does not exist")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-exe-help
|
||||
TARGET omnitrace-exe
|
||||
ARGS --help
|
||||
LABELS omnitrace-exe
|
||||
TIMEOUT 15
|
||||
PASS_REGULAR_EXPRESSION
|
||||
".*\\\[omnitrace\\\] Usage:.*\\\[DEBUG OPTIONS\\\].*\\\[MODE OPTIONS\\\].*\\\[LIBRARY OPTIONS\\\].*\\\[SYMBOL SELECTION OPTIONS\\\].*\\\[RUNTIME OPTIONS\\\].*\\\[GRANULARITY OPTIONS\\\].*\\\[DYNINST OPTIONS\\\].*"
|
||||
)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-exe-simulate-ls
|
||||
TARGET omnitrace-exe
|
||||
ARGS --simulate --print-format json txt xml -- ls
|
||||
TIMEOUT 60)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-exe-simulate-ls-check
|
||||
DEPENDS omnitrace-exe-simulate-ls
|
||||
COMMAND ls
|
||||
WORKING_DIRECTORY
|
||||
${PROJECT_BINARY_DIR}/omnitrace-tests-output/omnitrace-exe-simulate-ls
|
||||
TIMEOUT 30
|
||||
PASS_REGULAR_EXPRESSION
|
||||
".*available-instr.json.*available-instr.txt.*available-instr.xml.*excluded-instr.json.*excluded-instr.txt.*excluded-instr.xml.*instrumented-instr.json.*instrumented-instr.txt.*instrumented-instr.xml.*overlapping-instr.json.*overlapping-instr.txt.*overlapping-instr.xml.*"
|
||||
)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-avail-help
|
||||
TARGET omnitrace-avail
|
||||
ARGS --help
|
||||
LABELS omnitrace-avail
|
||||
TIMEOUT 15
|
||||
PASS_REGULAR_EXPRESSION
|
||||
".*\\\[omnitrace-avail\\\] Usage:.*\\\[CATEGORIES\\\].*\\\[VIEW OPTIONS\\\].*\\\[COLUMN OPTIONS\\\].*\\\[WIDTH OPTIONS\\\].*\\\[OUTPUT OPTIONS\\\].*"
|
||||
)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-avail-filter-wall-clock-available
|
||||
TARGET omnitrace-avail
|
||||
ARGS -r wall_clock -C --available
|
||||
LABELS omnitrace-avail
|
||||
TIMEOUT 15
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"\\\|[-]+\\\|\n\\\|[ ]+COMPONENT[ ]+\\\|\n\\\|[-]+\\\|\n\\\| (wall_clock)[ ]+\\\|\n\\\| (sampling_wall_clock)[ ]+\\\|\n\\\|[-]+\\\|"
|
||||
)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-avail-category-filer-omnitrace
|
||||
TARGET omnitrace-avail
|
||||
ARGS --categories settings::omnitrace --brief
|
||||
LABELS omnitrace-avail
|
||||
TIMEOUT 15
|
||||
PASS_REGULAR_EXPRESSION "OMNITRACE_(SETTINGS_DESC|OUTPUT_FILE|OUTPUT_PREFIX)"
|
||||
FAIL_REGULAR_EXPRESSION
|
||||
"OMNITRACE_(ADD_SECONDARY|SCIENTIFIC|PRECISION|MEMORY_PRECISION|TIMING_PRECISION)"
|
||||
)
|
||||
|
||||
omnitrace_add_bin_test(
|
||||
NAME omnitrace-avail-category-filer-timemory
|
||||
TARGET omnitrace-avail
|
||||
ARGS --categories settings::timemory --brief
|
||||
LABELS omnitrace-avail
|
||||
TIMEOUT 15
|
||||
PASS_REGULAR_EXPRESSION
|
||||
"OMNITRACE_(ADD_SECONDARY|SCIENTIFIC|PRECISION|MEMORY_PRECISION|TIMING_PRECISION)"
|
||||
FAIL_REGULAR_EXPRESSION "OMNITRACE_(SETTINGS_DESC|OUTPUT_FILE)")
|
||||
@@ -1,186 +1,14 @@
|
||||
# ------------------------------------------------------------------------------#
|
||||
# ----------------------------------------------------------------------------- #
|
||||
#
|
||||
# omnitrace interface library
|
||||
# omnitrace: contains all instrumentation functionality
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
add_library(omnitrace-interface-library INTERFACE)
|
||||
add_library(omnitrace::omnitrace-interface-library ALIAS omnitrace-interface-library)
|
||||
|
||||
target_include_directories(
|
||||
omnitrace-interface-library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
target_include_directories(omnitrace-interface-library SYSTEM
|
||||
INTERFACE ${perfetto_DIR}/sdk)
|
||||
|
||||
target_compile_definitions(
|
||||
omnitrace-interface-library
|
||||
INTERFACE OMNITRACE_MAX_THREADS=${OMNITRACE_MAX_THREADS}
|
||||
$<IF:$<BOOL:${OMNITRACE_CUSTOM_DATA_SOURCE}>,CUSTOM_DATA_SOURCE,>)
|
||||
|
||||
target_link_libraries(
|
||||
omnitrace-interface-library
|
||||
INTERFACE $<BUILD_INTERFACE:omnitrace::omnitrace-headers>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-threading>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-compile-options>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-hip>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-roctracer>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-rocm-smi>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-mpi>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
|
||||
$<BUILD_INTERFACE:timemory::timemory-headers>
|
||||
$<BUILD_INTERFACE:timemory::timemory-gotcha>
|
||||
$<BUILD_INTERFACE:timemory::timemory-cxx-static>
|
||||
$<IF:$<BOOL:${OMNITRACE_USE_SANITIZER}>,omnitrace::omnitrace-sanitizer,>)
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
# omnitrace-dl: contains minimal symbols and dlopen's omnitrace
|
||||
#
|
||||
# omnitrace object library
|
||||
# omnitrace-user: contains symbols for user API
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
# ----------------------------------------------------------------------------- #
|
||||
|
||||
add_library(omnitrace-object-library OBJECT)
|
||||
add_library(omnitrace::omnitrace-object-library ALIAS omnitrace-object-library)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/library/defines.hpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/library/defines.hpp @ONLY)
|
||||
|
||||
set(library_sources
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/api.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/config.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/cpu_freq.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/critical_trace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/kokkosp.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/gpu.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/perfetto.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/ptl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/sampling.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/state.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_data.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_sampler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/timemory.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/backtrace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/fork_gotcha.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/mpi_gotcha.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/omnitrace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/pthread_gotcha.cpp
|
||||
${perfetto_DIR}/sdk/perfetto.cc)
|
||||
|
||||
set(library_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/api.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/config.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/common.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/cpu_freq.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/critical_trace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/debug.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/gpu.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/perfetto.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/ptl.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/sampling.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/state.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_data.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_sampler.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/timemory.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fwd.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/backtrace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fork_gotcha.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/functors.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/mpi_gotcha.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/omnitrace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/rocm_smi.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/pthread_gotcha.hpp
|
||||
${perfetto_DIR}/sdk/perfetto.h)
|
||||
|
||||
target_sources(omnitrace-object-library PRIVATE ${library_sources} ${library_headers})
|
||||
|
||||
if(OMNITRACE_USE_ROCTRACER)
|
||||
target_sources(
|
||||
omnitrace-object-library
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_USE_ROCM_SMI)
|
||||
target_sources(omnitrace-object-library
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/rocm_smi.cpp)
|
||||
endif()
|
||||
|
||||
target_link_libraries(omnitrace-object-library PRIVATE omnitrace-interface-library)
|
||||
|
||||
if(OMNITRACE_DYNINST_API_RT)
|
||||
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
|
||||
DIRECTORY)
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace shared library
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
add_library(omnitrace-library SHARED $<TARGET_OBJECTS:omnitrace-object-library>)
|
||||
add_library(omnitrace::omnitrace-library ALIAS omnitrace-library)
|
||||
|
||||
target_link_libraries(omnitrace-library PRIVATE omnitrace-interface-library)
|
||||
|
||||
set_target_properties(
|
||||
omnitrace-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
INSTALL_RPATH
|
||||
"\$ORIGIN:\$ORIGIN/timemory/libunwind:\$ORIGIN/dyninst-tpls/libs")
|
||||
|
||||
install(
|
||||
TARGETS omnitrace-library
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OPTIONAL)
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace dl library
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(CMAKE_SKIP_RPATH OFF)
|
||||
set(BUILD_RPATH_USE_ORIGIN ON)
|
||||
|
||||
add_library(omnitrace-dl-library SHARED)
|
||||
add_library(omnitrace::omnitrace-dl-library ALIAS omnitrace-dl-library)
|
||||
|
||||
target_sources(omnitrace-dl-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src/dl.cpp)
|
||||
target_link_libraries(omnitrace-dl-library PRIVATE ${dl_LIBRARY})
|
||||
|
||||
check_cxx_compiler_flag("-fno-exceptions" omnitrace_dl_library_fno_exceptions)
|
||||
check_cxx_compiler_flag("-ftls-model=local-dynamic"
|
||||
omnitrace_dl_library_ftls_module_local_dynamic)
|
||||
|
||||
if(OMNITRACE_BUILD_DEVELOPER)
|
||||
if(omnitrace_dl_library_fno_exceptions)
|
||||
target_compile_options(omnitrace-dl-library PRIVATE -fno-exceptions)
|
||||
endif()
|
||||
|
||||
if(omnitrace_dl_library_ftls_module_local_dynamic)
|
||||
target_compile_options(omnitrace-dl-library PRIVATE -ftls-model=local-dynamic)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
omnitrace-dl-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace-dl
|
||||
CXX_VISIBILITY_PRESET "protected"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
BUILD_RPATH "\$ORIGIN"
|
||||
INSTALL_RPATH "\$ORIGIN")
|
||||
|
||||
install(
|
||||
TARGETS omnitrace-dl-library
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OPTIONAL)
|
||||
add_subdirectory(common)
|
||||
add_subdirectory(omnitrace)
|
||||
add_subdirectory(omnitrace-dl)
|
||||
add_subdirectory(omnitrace-user)
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace common headers
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
add_library(omnitrace-common-library INTERFACE)
|
||||
add_library(omnitrace::common-library ALIAS omnitrace-common-library)
|
||||
|
||||
target_sources(
|
||||
omnitrace-common-library
|
||||
INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/defines.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/delimit.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/environment.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/invoke.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/join.hpp)
|
||||
|
||||
get_filename_component(COMMON_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" DIRECTORY)
|
||||
|
||||
target_include_directories(omnitrace-common-library INTERFACE ${COMMON_INCLUDE_DIR})
|
||||
target_compile_definitions(omnitrace-common-library
|
||||
INTERFACE $<BUILD_INTERFACE:OMNITRACE_INTERNAL_BUILD>)
|
||||
@@ -0,0 +1,36 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#define OMNITRACE_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
|
||||
#define OMNITRACE_VISIBILITY(MODE) OMNITRACE_ATTRIBUTE(visibility(MODE))
|
||||
#define OMNITRACE_PUBLIC_API OMNITRACE_VISIBILITY("default")
|
||||
#define OMNITRACE_HIDDEN_API OMNITRACE_VISIBILITY("hidden")
|
||||
#define OMNITRACE_WEAK_API OMNITRACE_ATTRIBUTE(weak)
|
||||
#define OMNITRACE_INLINE OMNITRACE_ATTRIBUTE(__always_inline__)
|
||||
|
||||
#if defined(__cplusplus)
|
||||
# if !defined(OMNITRACE_FOLD_EXPRESSION)
|
||||
# define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
# endif
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename ContainerT = std::vector<std::string>>
|
||||
inline ContainerT
|
||||
delimit(const std::string& line, const char* delimiters = "\"',;: ");
|
||||
|
||||
template <typename ContainerT>
|
||||
inline ContainerT
|
||||
delimit(const std::string& line, const char* delimiters)
|
||||
{
|
||||
ContainerT _result{};
|
||||
size_t _beginp = 0; // position that is the beginning of the new string
|
||||
size_t _delimp = 0; // position of the delimiter in the string
|
||||
while(_beginp < line.length() && _delimp < line.length())
|
||||
{
|
||||
// find the first character (starting at _delimp) that is not a delimiter
|
||||
_beginp = line.find_first_not_of(delimiters, _delimp);
|
||||
// if no a character after or at _end that is not a delimiter is not found
|
||||
// then we are done
|
||||
if(_beginp == std::string::npos) break;
|
||||
// starting at the position of the new string, find the next delimiter
|
||||
_delimp = line.find_first_of(delimiters, _beginp);
|
||||
std::string _tmp{};
|
||||
// starting at the position of the new string, get the characters
|
||||
// between this position and the next delimiter
|
||||
_tmp = line.substr(_beginp, _delimp - _beginp);
|
||||
// don't add empty strings
|
||||
if(!_tmp.empty()) _result.emplace(_result.end(), _tmp);
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace common
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,77 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline std::string
|
||||
get_env(const char* env_id, const char* _default)
|
||||
{
|
||||
if(strlen(env_id) == 0) return _default;
|
||||
char* env_var = ::std::getenv(env_id);
|
||||
if(env_var) return std::string{ env_var };
|
||||
return _default;
|
||||
}
|
||||
|
||||
inline int
|
||||
get_env(const char* env_id, int _default)
|
||||
{
|
||||
if(strlen(env_id) == 0) return _default;
|
||||
char* env_var = ::std::getenv(env_id);
|
||||
if(env_var) return std::stoi(env_var);
|
||||
return _default;
|
||||
}
|
||||
|
||||
inline bool
|
||||
get_env(const char* env_id, bool _default)
|
||||
{
|
||||
if(strlen(env_id) == 0) return _default;
|
||||
char* env_var = ::std::getenv(env_id);
|
||||
if(env_var)
|
||||
{
|
||||
if(std::string_view{ env_var }.find_first_not_of("0123456789") ==
|
||||
std::string_view::npos)
|
||||
return static_cast<bool>(std::stoi(env_var));
|
||||
else
|
||||
{
|
||||
for(size_t i = 0; i < strlen(env_var); ++i)
|
||||
env_var[i] = tolower(env_var[i]);
|
||||
for(const auto& itr : { "off", "false", "no", "n", "f", "0" })
|
||||
if(strcmp(env_var, itr) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace common
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,114 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/defines.h"
|
||||
#include "common/join.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#if !defined(OMNITRACE_COMMON_LIBRARY_NAME)
|
||||
# define OMNITRACE_COMMON_LIBRARY_NAME "common"
|
||||
# error OMNITRACE_COMMON_LIBRARY_NAME must be defined
|
||||
#endif
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename FuncT, typename... Args>
|
||||
inline auto
|
||||
invoke(const char* _name, FuncT&& _func, Args... _args) OMNITRACE_HIDDEN_API;
|
||||
|
||||
inline int32_t&
|
||||
get_guard()
|
||||
{
|
||||
static thread_local int32_t _v = 0;
|
||||
return _v;
|
||||
}
|
||||
|
||||
inline int64_t
|
||||
get_thread_index()
|
||||
{
|
||||
static std::atomic<int64_t> _c{ 0 };
|
||||
static thread_local auto _v = _c++;
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename FuncT, typename... Args>
|
||||
auto
|
||||
invoke(const char* _name, int _verbose, FuncT&& _func, Args... _args)
|
||||
{
|
||||
if(_func)
|
||||
{
|
||||
struct decrement_guard
|
||||
{
|
||||
// decrement the guard as it exits the scope
|
||||
~decrement_guard() { --get_guard(); }
|
||||
} _unlk{};
|
||||
|
||||
// if _lk is ever greater than zero on the same thread, this
|
||||
// means a function within the current function is calling
|
||||
// our instrumentation so we ignore the call
|
||||
int32_t _lk = get_guard()++;
|
||||
if(_lk == 0)
|
||||
{
|
||||
if(_verbose > 3)
|
||||
{
|
||||
fflush(stderr);
|
||||
fprintf(stderr,
|
||||
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME "][%li] %s(%s)\n",
|
||||
get_thread_index(), _name, join(", ", _args...).c_str());
|
||||
fflush(stderr);
|
||||
}
|
||||
return std::invoke(std::forward<FuncT>(_func), _args...);
|
||||
}
|
||||
else if(_verbose > 2)
|
||||
{
|
||||
fflush(stderr);
|
||||
fprintf(stderr,
|
||||
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME
|
||||
"][%li] %s(%s) was guarded :: value = %i\n",
|
||||
get_thread_index(), _name, join(", ", _args...).c_str(), _lk);
|
||||
fflush(stderr);
|
||||
}
|
||||
}
|
||||
else if(_verbose >= 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"[omnitrace][" OMNITRACE_COMMON_LIBRARY_NAME
|
||||
"][%li] %s(%s) ignored :: null function pointer\n",
|
||||
get_thread_index(), _name, join(", ", _args...).c_str());
|
||||
}
|
||||
|
||||
using return_type = decltype(std::invoke(std::forward<FuncT>(_func), _args...));
|
||||
if constexpr(!std::is_void<return_type>::value) return return_type();
|
||||
}
|
||||
} // namespace
|
||||
} // namespace common
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,55 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#if !defined(OMNITRACE_FOLD_EXPRESSION)
|
||||
# define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
#endif
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace common
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename DelimT, typename... Args>
|
||||
auto
|
||||
join(DelimT&& _delim, Args&&... _args)
|
||||
{
|
||||
std::stringstream _ss{};
|
||||
OMNITRACE_FOLD_EXPRESSION(_ss << _delim << _args);
|
||||
if constexpr(std::is_same<DelimT, char>::value)
|
||||
{
|
||||
return _ss.str().substr(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _ss.str().substr(std::string{ _delim }.length());
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
} // namespace common
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,55 @@
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace dl library
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(CMAKE_SKIP_RPATH OFF)
|
||||
set(BUILD_RPATH_USE_ORIGIN ON)
|
||||
|
||||
add_library(omnitrace-dl-library SHARED)
|
||||
add_library(omnitrace::omnitrace-dl-library ALIAS omnitrace-dl-library)
|
||||
|
||||
target_sources(omnitrace-dl-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/dl.cpp)
|
||||
target_link_libraries(omnitrace-dl-library PRIVATE ${dl_LIBRARY}
|
||||
omnitrace::common-library)
|
||||
|
||||
check_cxx_compiler_flag("-fno-exceptions" omnitrace_dl_library_fno_exceptions)
|
||||
check_cxx_compiler_flag("-ftls-model=local-dynamic"
|
||||
omnitrace_dl_library_ftls_module_local_dynamic)
|
||||
|
||||
if(OMNITRACE_BUILD_DEVELOPER)
|
||||
if(omnitrace_dl_library_fno_exceptions)
|
||||
target_compile_options(omnitrace-dl-library PRIVATE -fno-exceptions)
|
||||
endif()
|
||||
|
||||
if(omnitrace_dl_library_ftls_module_local_dynamic)
|
||||
target_compile_options(omnitrace-dl-library PRIVATE -ftls-model=local-dynamic)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
omnitrace_target_compile_definitions(
|
||||
omnitrace-dl-library PRIVATE OMNITRACE_USE_OMPT=$<BOOL:${OMNITRACE_USE_OMPT}>)
|
||||
|
||||
set_target_properties(
|
||||
omnitrace-dl-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace-dl
|
||||
CXX_VISIBILITY_PRESET "protected"
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
BUILD_RPATH "\$ORIGIN"
|
||||
INSTALL_RPATH "\$ORIGIN")
|
||||
|
||||
install(
|
||||
TARGETS omnitrace-dl-library
|
||||
EXPORT omnitrace-dl-library-targets
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OPTIONAL)
|
||||
|
||||
install(
|
||||
EXPORT omnitrace-dl-library-targets
|
||||
FILE omnitrace-dl-library-targets.cmake
|
||||
NAMESPACE omnitrace::
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/omnitrace)
|
||||
@@ -22,6 +22,15 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#define OMNITRACE_COMMON_LIBRARY_NAME "dl"
|
||||
|
||||
#include "common/defines.h"
|
||||
#include "common/delimit.hpp"
|
||||
#include "common/environment.hpp"
|
||||
#include "common/invoke.hpp"
|
||||
#include "common/join.hpp"
|
||||
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
@@ -38,15 +47,15 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define OMNITRACE_FOLD_EXPRESSION(...) ((__VA_ARGS__), ...)
|
||||
#define OMNITRACE_VISIBLE __attribute__((visibility("default")))
|
||||
#define OMNITRACE_HIDDEN __attribute__((visibility("internal")))
|
||||
#define OMNITRACE_INLINE __attribute__((__always_inline__))
|
||||
#if !defined(OMNITRACE_USE_OMPT)
|
||||
# define OMNITRACE_USE_OMPT 0
|
||||
#endif
|
||||
|
||||
#define OMNITRACE_DLSYM(VARNAME, HANDLE, FUNCNAME) \
|
||||
if(HANDLE) \
|
||||
{ \
|
||||
*(void**) (&VARNAME) = dlsym(HANDLE, FUNCNAME); \
|
||||
if(VARNAME == nullptr && _omnitrace_dl_verbose >= 0) \
|
||||
if(VARNAME == nullptr && _omnitrace_dl_verbose >= _warn_verbose) \
|
||||
{ \
|
||||
fprintf(stderr, "[omnitrace][dl][pid=%i]> %s :: %s\n", getpid(), FUNCNAME, \
|
||||
dlerror()); \
|
||||
@@ -61,50 +70,45 @@
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void omnitrace_init_library(void) OMNITRACE_VISIBLE;
|
||||
void omnitrace_init(const char*, bool, const char*) OMNITRACE_VISIBLE;
|
||||
void omnitrace_finalize(void) OMNITRACE_VISIBLE;
|
||||
void omnitrace_set_env(const char* env_name, const char* env_val) OMNITRACE_VISIBLE;
|
||||
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_VISIBLE;
|
||||
void omnitrace_push_trace(const char* name) OMNITRACE_VISIBLE;
|
||||
void omnitrace_pop_trace(const char* name) OMNITRACE_VISIBLE;
|
||||
struct ompt_start_tool_result_t;
|
||||
|
||||
void omnitrace_init_library(void) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_init(const char*, bool, const char*) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_finalize(void) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_set_env(const char* env_name,
|
||||
const char* env_val) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_set_mpi(bool use, bool attached) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_push_trace(const char* name) OMNITRACE_PUBLIC_API;
|
||||
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
|
||||
|
||||
void omnitrace_user_start_trace_dl(void) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_user_stop_trace_dl(void) OMNITRACE_HIDDEN_API;
|
||||
|
||||
void omnitrace_user_start_thread_trace_dl(void) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_user_stop_thread_trace_dl(void) OMNITRACE_HIDDEN_API;
|
||||
|
||||
void omnitrace_user_push_region_dl(const char*) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_user_pop_region_dl(const char*) OMNITRACE_HIDDEN_API;
|
||||
|
||||
ompt_start_tool_result_t* ompt_start_tool(unsigned int,
|
||||
const char*) OMNITRACE_PUBLIC_API;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
inline namespace omnitrace
|
||||
namespace omnitrace
|
||||
{
|
||||
inline namespace dl
|
||||
{
|
||||
namespace
|
||||
{
|
||||
inline int
|
||||
get_omnitrace_env();
|
||||
|
||||
bool
|
||||
get_env(const char* env_id, bool _default);
|
||||
|
||||
std::string
|
||||
get_env(const char* env_id, const char* _default);
|
||||
|
||||
int
|
||||
get_env(const char* env_id, int _default);
|
||||
|
||||
template <typename DelimT, typename... Args>
|
||||
auto
|
||||
join(DelimT&& _delim, Args&&... _args)
|
||||
get_omnitrace_env()
|
||||
{
|
||||
std::stringstream _ss{};
|
||||
OMNITRACE_FOLD_EXPRESSION(_ss << _delim << _args);
|
||||
if constexpr(std::is_same<DelimT, char>::value)
|
||||
{
|
||||
return _ss.str().substr(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return _ss.str().substr(std::string{ _delim }.length());
|
||||
}
|
||||
auto&& _debug = get_env("OMNITRACE_DEBUG", false);
|
||||
return get_env("OMNITRACE_VERBOSE", (_debug) ? 100 : 0);
|
||||
}
|
||||
|
||||
// environment priority:
|
||||
// - OMNITRACE_DL_DEBUG
|
||||
// - OMNITRACE_DL_VERBOSE
|
||||
@@ -114,10 +118,6 @@ int _omnitrace_dl_verbose = get_env("OMNITRACE_DL_DEBUG", false)
|
||||
? 100
|
||||
: get_env("OMNITRACE_DL_VERBOSE", get_omnitrace_env());
|
||||
|
||||
template <typename ContainerT = std::vector<std::string>>
|
||||
inline ContainerT
|
||||
delimit(const std::string& line, const char* delimiters = "\"',;: ");
|
||||
|
||||
// The docs for dlopen suggest that the combination of RTLD_LOCAL + RTLD_DEEPBIND
|
||||
// (when available) helps ensure that the symbols in the instrumentation library
|
||||
// libomnitrace.so will use it's own symbols... not symbols that are potentially
|
||||
@@ -162,39 +162,38 @@ const char* _omnitrace_dl_dlopen_descr = "RTLD_LAZY | RTLD_LOCAL";
|
||||
#endif
|
||||
|
||||
/// This class contains function pointers for omnitrace's instrumentation functions
|
||||
struct OMNITRACE_HIDDEN indirect
|
||||
struct OMNITRACE_HIDDEN_API indirect
|
||||
{
|
||||
explicit OMNITRACE_INLINE indirect(std::string libpath)
|
||||
: m_libpath{ find_path(std::move(libpath)) }
|
||||
OMNITRACE_INLINE indirect(std::string omnilib, std::string userlib)
|
||||
: m_omnilib{ find_path(std::move(omnilib)) }
|
||||
, m_userlib{ find_path(std::move(userlib)) }
|
||||
{
|
||||
if(_omnitrace_dl_verbose > 0)
|
||||
{
|
||||
fprintf(stderr, "[omnitrace][dl][pid=%i] libomnitrace.so resolved to '%s'\n",
|
||||
getpid(), m_libpath.c_str());
|
||||
getpid(), m_omnilib.c_str());
|
||||
}
|
||||
auto _omni_hsa_lib = m_libpath;
|
||||
auto _omni_hsa_lib = m_omnilib;
|
||||
const char* _hsa_lib = getenv("HSA_TOOLS_LIB");
|
||||
if(_hsa_lib) _omni_hsa_lib.append(":").append(_hsa_lib);
|
||||
setenv("HSA_TOOLS_LIB", _omni_hsa_lib.c_str(), 1);
|
||||
open();
|
||||
m_omnihandle = open(m_omnilib);
|
||||
m_userhandle = open(m_userlib);
|
||||
init();
|
||||
}
|
||||
|
||||
OMNITRACE_INLINE ~indirect() { dlclose(m_libhandle); }
|
||||
OMNITRACE_INLINE ~indirect() { dlclose(m_omnihandle); }
|
||||
|
||||
OMNITRACE_INLINE void open()
|
||||
static OMNITRACE_INLINE void* open(const std::string& _lib)
|
||||
{
|
||||
if(m_libhandle) return;
|
||||
|
||||
auto* libhandle = dlopen(m_libpath.c_str(), _omnitrace_dl_dlopen_flags);
|
||||
auto* libhandle = dlopen(_lib.c_str(), _omnitrace_dl_dlopen_flags);
|
||||
|
||||
if(libhandle)
|
||||
{
|
||||
m_libhandle = libhandle;
|
||||
if(_omnitrace_dl_verbose > 0)
|
||||
{
|
||||
fprintf(stderr, "[omnitrace][dl][pid=%i] dlopen(%s, %s) :: success\n",
|
||||
getpid(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr);
|
||||
getpid(), _lib.c_str(), _omnitrace_dl_dlopen_descr);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -203,26 +202,48 @@ struct OMNITRACE_HIDDEN indirect
|
||||
{
|
||||
perror("dlopen");
|
||||
fprintf(stderr, "[omnitrace][dl][pid=%i] dlopen(%s, %s) :: %s\n",
|
||||
getpid(), m_libpath.c_str(), _omnitrace_dl_dlopen_descr,
|
||||
dlerror());
|
||||
getpid(), _lib.c_str(), _omnitrace_dl_dlopen_descr, dlerror());
|
||||
}
|
||||
}
|
||||
|
||||
dlerror(); // Clear any existing error
|
||||
|
||||
return libhandle;
|
||||
}
|
||||
|
||||
OMNITRACE_INLINE void init()
|
||||
{
|
||||
if(!m_libhandle) open();
|
||||
if(!m_omnihandle) m_omnihandle = open(m_omnilib);
|
||||
|
||||
int _warn_verbose = 0;
|
||||
// Initialize all pointers
|
||||
OMNITRACE_DLSYM(omnitrace_init_library_f, m_libhandle, "omnitrace_init_library");
|
||||
OMNITRACE_DLSYM(omnitrace_init_f, m_libhandle, "omnitrace_init");
|
||||
OMNITRACE_DLSYM(omnitrace_finalize_f, m_libhandle, "omnitrace_finalize");
|
||||
OMNITRACE_DLSYM(omnitrace_set_env_f, m_libhandle, "omnitrace_set_env");
|
||||
OMNITRACE_DLSYM(omnitrace_set_mpi_f, m_libhandle, "omnitrace_set_mpi");
|
||||
OMNITRACE_DLSYM(omnitrace_push_trace_f, m_libhandle, "omnitrace_push_trace");
|
||||
OMNITRACE_DLSYM(omnitrace_pop_trace_f, m_libhandle, "omnitrace_pop_trace");
|
||||
OMNITRACE_DLSYM(omnitrace_init_library_f, m_omnihandle, "omnitrace_init_library");
|
||||
OMNITRACE_DLSYM(omnitrace_init_f, m_omnihandle, "omnitrace_init");
|
||||
OMNITRACE_DLSYM(omnitrace_finalize_f, m_omnihandle, "omnitrace_finalize");
|
||||
OMNITRACE_DLSYM(omnitrace_set_env_f, m_omnihandle, "omnitrace_set_env");
|
||||
OMNITRACE_DLSYM(omnitrace_set_mpi_f, m_omnihandle, "omnitrace_set_mpi");
|
||||
OMNITRACE_DLSYM(omnitrace_push_trace_f, m_omnihandle, "omnitrace_push_trace");
|
||||
OMNITRACE_DLSYM(omnitrace_pop_trace_f, m_omnihandle, "omnitrace_pop_trace");
|
||||
OMNITRACE_DLSYM(omnitrace_push_region_f, m_omnihandle, "omnitrace_push_region");
|
||||
OMNITRACE_DLSYM(omnitrace_pop_region_f, m_omnihandle, "omnitrace_pop_region");
|
||||
#if OMNITRACE_USE_OMPT == 0
|
||||
_warn_verbose = 5;
|
||||
#endif
|
||||
OMNITRACE_DLSYM(ompt_start_tool_f, m_omnihandle, "ompt_start_tool");
|
||||
|
||||
if(!m_userhandle) m_userhandle = open(m_userlib);
|
||||
_warn_verbose = 0;
|
||||
OMNITRACE_DLSYM(omnitrace_user_configure_f, m_userhandle,
|
||||
"omnitrace_user_configure");
|
||||
|
||||
if(omnitrace_user_configure_f)
|
||||
{
|
||||
(*omnitrace_user_configure_f)(
|
||||
&omnitrace_user_start_trace_dl, &omnitrace_user_stop_trace_dl,
|
||||
&omnitrace_user_start_thread_trace_dl,
|
||||
&omnitrace_user_stop_thread_trace_dl, &omnitrace_user_push_region_dl,
|
||||
&omnitrace_user_pop_region_dl);
|
||||
}
|
||||
}
|
||||
|
||||
static OMNITRACE_INLINE std::string find_path(std::string&& _path)
|
||||
@@ -246,196 +267,170 @@ struct OMNITRACE_HIDDEN indirect
|
||||
}
|
||||
|
||||
public:
|
||||
void (*omnitrace_init_library_f)(void) = nullptr;
|
||||
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
|
||||
void (*omnitrace_finalize_f)(void) = nullptr;
|
||||
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
|
||||
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
|
||||
void (*omnitrace_push_trace_f)(const char*) = nullptr;
|
||||
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
|
||||
void (*omnitrace_init_library_f)(void) = nullptr;
|
||||
void (*omnitrace_init_f)(const char*, bool, const char*) = nullptr;
|
||||
void (*omnitrace_finalize_f)(void) = nullptr;
|
||||
void (*omnitrace_set_env_f)(const char*, const char*) = nullptr;
|
||||
void (*omnitrace_set_mpi_f)(bool, bool) = nullptr;
|
||||
void (*omnitrace_push_trace_f)(const char*) = nullptr;
|
||||
void (*omnitrace_pop_trace_f)(const char*) = nullptr;
|
||||
void (*omnitrace_push_region_f)(const char*) = nullptr;
|
||||
void (*omnitrace_pop_region_f)(const char*) = nullptr;
|
||||
void (*omnitrace_user_configure_f)(void (*)(void), void (*)(void), void (*)(void),
|
||||
void (*)(void), void (*)(const char*),
|
||||
void (*)(const char*)) = nullptr;
|
||||
ompt_start_tool_result_t* (*ompt_start_tool_f)(unsigned int, const char*);
|
||||
|
||||
private:
|
||||
void* m_libhandle = nullptr;
|
||||
std::string m_libpath = {};
|
||||
void* m_omnihandle = nullptr;
|
||||
void* m_userhandle = nullptr;
|
||||
std::string m_omnilib = {};
|
||||
std::string m_userlib = {};
|
||||
};
|
||||
|
||||
inline indirect&
|
||||
get_indirect() OMNITRACE_HIDDEN;
|
||||
get_indirect() OMNITRACE_HIDDEN_API;
|
||||
|
||||
template <typename FuncT, typename... Args>
|
||||
inline void
|
||||
invoke(const char* _name, FuncT&& _func, Args... _args) OMNITRACE_HIDDEN;
|
||||
indirect&
|
||||
get_indirect()
|
||||
{
|
||||
static auto _v =
|
||||
indirect{ get_env("OMNITRACE_LIBRARY", "libomnitrace.so"),
|
||||
get_env("OMNITRACE_USER_LIBRARY", "libomnitrace-user.so") };
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
get_active()
|
||||
{
|
||||
static bool _v = false;
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
get_enabled()
|
||||
{
|
||||
static std::atomic<bool> _v{ get_env("OMNITRACE_INIT_ENABLED", true) };
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
get_thread_enabled()
|
||||
{
|
||||
static thread_local bool _v = get_enabled();
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
get_count()
|
||||
{
|
||||
static std::atomic<int64_t> _v{ 0 };
|
||||
return _v;
|
||||
}
|
||||
|
||||
auto&
|
||||
get_thread_count()
|
||||
{
|
||||
static thread_local int64_t _v = 0;
|
||||
return _v;
|
||||
}
|
||||
} // namespace
|
||||
} // namespace dl
|
||||
} // namespace omnitrace
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
|
||||
#define OMNITRACE_DL_INVOKE(...) \
|
||||
::omnitrace::common::invoke(__FUNCTION__, ::omnitrace::dl::_omnitrace_dl_verbose, \
|
||||
__VA_ARGS__)
|
||||
|
||||
using omnitrace::get_indirect;
|
||||
namespace dl = omnitrace::dl;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void omnitrace_init_library(void)
|
||||
{
|
||||
invoke(__FUNCTION__, get_indirect().omnitrace_init_library_f);
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_library_f);
|
||||
}
|
||||
|
||||
void omnitrace_init(const char* a, bool b, const char* c)
|
||||
{
|
||||
invoke(__FUNCTION__, get_indirect().omnitrace_init_f, a, b, c);
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_init_f, a, b, c);
|
||||
dl::get_active() = true;
|
||||
}
|
||||
|
||||
void omnitrace_finalize(void)
|
||||
{
|
||||
invoke(__FUNCTION__, get_indirect().omnitrace_finalize_f);
|
||||
dl::get_active() = false;
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_finalize_f);
|
||||
}
|
||||
|
||||
void omnitrace_push_trace(const char* name)
|
||||
{
|
||||
invoke(__FUNCTION__, get_indirect().omnitrace_push_trace_f, name);
|
||||
if(!dl::get_active()) return;
|
||||
if(dl::get_thread_enabled())
|
||||
{
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_trace_f, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
++dl::get_thread_count();
|
||||
}
|
||||
}
|
||||
|
||||
void omnitrace_pop_trace(const char* name)
|
||||
{
|
||||
invoke(__FUNCTION__, get_indirect().omnitrace_pop_trace_f, name);
|
||||
if(!dl::get_active()) return;
|
||||
if(dl::get_thread_enabled())
|
||||
{
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_trace_f, name);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(dl::get_thread_count()-- == 0) omnitrace_user_start_thread_trace_dl();
|
||||
}
|
||||
}
|
||||
|
||||
void omnitrace_set_env(const char* a, const char* b)
|
||||
{
|
||||
setenv(a, b, 0);
|
||||
invoke(__FUNCTION__, get_indirect().omnitrace_set_env_f, a, b);
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_set_env_f, a, b);
|
||||
}
|
||||
|
||||
void omnitrace_set_mpi(bool a, bool b)
|
||||
{
|
||||
invoke(__FUNCTION__, get_indirect().omnitrace_set_mpi_f, a, b);
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_set_mpi_f, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------//
|
||||
void omnitrace_user_start_trace_dl(void) { dl::get_enabled().store(true); }
|
||||
void omnitrace_user_stop_trace_dl(void) { dl::get_enabled().store(false); }
|
||||
void omnitrace_user_start_thread_trace_dl(void) { dl::get_thread_enabled() = true; }
|
||||
void omnitrace_user_stop_thread_trace_dl(void) { dl::get_thread_enabled() = false; }
|
||||
|
||||
inline namespace omnitrace
|
||||
{
|
||||
inline namespace dl
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename ContainerT>
|
||||
inline ContainerT
|
||||
delimit(const std::string& line, const char* delimiters)
|
||||
{
|
||||
ContainerT _result{};
|
||||
size_t _beginp = 0; // position that is the beginning of the new string
|
||||
size_t _delimp = 0; // position of the delimiter in the string
|
||||
while(_beginp < line.length() && _delimp < line.length())
|
||||
void omnitrace_user_push_region_dl(const char* name)
|
||||
{
|
||||
// find the first character (starting at _delimp) that is not a delimiter
|
||||
_beginp = line.find_first_not_of(delimiters, _delimp);
|
||||
// if no a character after or at _end that is not a delimiter is not found
|
||||
// then we are done
|
||||
if(_beginp == std::string::npos) break;
|
||||
// starting at the position of the new string, find the next delimiter
|
||||
_delimp = line.find_first_of(delimiters, _beginp);
|
||||
std::string _tmp{};
|
||||
// starting at the position of the new string, get the characters
|
||||
// between this position and the next delimiter
|
||||
_tmp = line.substr(_beginp, _delimp - _beginp);
|
||||
// don't add empty strings
|
||||
if(!_tmp.empty()) _result.emplace(_result.end(), _tmp);
|
||||
if(!dl::get_active()) return;
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_push_region_f, name);
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
|
||||
std::string
|
||||
get_env(const char* env_id, const char* _default)
|
||||
{
|
||||
if(strlen(env_id) == 0) return _default;
|
||||
char* env_var = ::std::getenv(env_id);
|
||||
if(env_var) return std::string{ env_var };
|
||||
return _default;
|
||||
}
|
||||
|
||||
int
|
||||
get_env(const char* env_id, int _default)
|
||||
{
|
||||
if(strlen(env_id) == 0) return _default;
|
||||
char* env_var = ::std::getenv(env_id);
|
||||
if(env_var) return std::stoi(env_var);
|
||||
return _default;
|
||||
}
|
||||
|
||||
bool
|
||||
get_env(const char* env_id, bool _default)
|
||||
{
|
||||
if(strlen(env_id) == 0) return _default;
|
||||
char* env_var = ::std::getenv(env_id);
|
||||
if(env_var)
|
||||
void omnitrace_user_pop_region_dl(const char* name)
|
||||
{
|
||||
if(std::string{ env_var }.find_first_not_of("0123456789") == std::string::npos)
|
||||
return static_cast<bool>(std::stoi(env_var));
|
||||
else
|
||||
{
|
||||
for(size_t i = 0; i < strlen(env_var); ++i)
|
||||
env_var[i] = tolower(env_var[i]);
|
||||
for(const auto& itr : { "off", "false", "no", "n", "f", "0" })
|
||||
if(strcmp(env_var, itr) == 0) return false;
|
||||
}
|
||||
return true;
|
||||
if(!dl::get_active()) return;
|
||||
OMNITRACE_DL_INVOKE(get_indirect().omnitrace_pop_region_f, name);
|
||||
}
|
||||
return _default;
|
||||
}
|
||||
|
||||
int
|
||||
get_omnitrace_env()
|
||||
{
|
||||
auto&& _debug = get_env("OMNITRACE_DEBUG", false);
|
||||
return get_env("OMNITRACE_VERBOSE", (_debug) ? 100 : 0);
|
||||
}
|
||||
|
||||
indirect&
|
||||
get_indirect()
|
||||
{
|
||||
static auto _v = indirect{ get_env("OMNITRACE_LIBRARY", "libomnitrace.so") };
|
||||
return _v;
|
||||
}
|
||||
|
||||
int32_t&
|
||||
get_guard()
|
||||
{
|
||||
static thread_local int32_t _v = 0;
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename FuncT, typename... Args>
|
||||
void
|
||||
invoke(const char* _name, FuncT&& _func, Args... _args)
|
||||
{
|
||||
if(_func)
|
||||
ompt_start_tool_result_t* ompt_start_tool(unsigned int omp_version,
|
||||
const char* runtime_version)
|
||||
{
|
||||
// if _lk is ever greater than zero on the same thread, this
|
||||
// means a function within the current function is calling
|
||||
// our instrumentation so we ignore the call
|
||||
int32_t _lk = get_guard()++;
|
||||
if(_lk == 0)
|
||||
{
|
||||
std::invoke(std::forward<FuncT>(_func), _args...);
|
||||
}
|
||||
else if(_omnitrace_dl_verbose > 2)
|
||||
{
|
||||
fflush(stderr);
|
||||
fprintf(stderr, "[omnitrace][dl] call to %s was guarded :: value = %i\n",
|
||||
_name, _lk);
|
||||
fflush(stderr);
|
||||
}
|
||||
// decrement the guard as it exits the scope
|
||||
--get_guard();
|
||||
}
|
||||
else if(_omnitrace_dl_verbose >= 0)
|
||||
{
|
||||
fprintf(stderr, "[omnitrace][dl] %s\n",
|
||||
join("", "null function pointer to ", _name, ". Ignoring ", _name, "(",
|
||||
_args..., ")")
|
||||
.c_str());
|
||||
#if OMNITRACE_USE_OMPT == 0
|
||||
(void) omp_version;
|
||||
(void) runtime_version;
|
||||
return nullptr;
|
||||
#else
|
||||
if(!omnitrace::common::get_env("OMNITRACE_USE_OMPT", true)) return nullptr;
|
||||
return OMNITRACE_DL_INVOKE(get_indirect().ompt_start_tool_f, omp_version,
|
||||
runtime_version);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
} // namespace dl
|
||||
} // namespace omnitrace
|
||||
@@ -0,0 +1,61 @@
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace user library
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
set(CMAKE_BUILD_TYPE "Release")
|
||||
set(CMAKE_SKIP_RPATH OFF)
|
||||
set(BUILD_RPATH_USE_ORIGIN ON)
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET "hidden")
|
||||
set(CMAKE_VISIBILITY_INLINES_HIDDEN ON)
|
||||
|
||||
add_library(omnitrace-user-library SHARED)
|
||||
add_library(omnitrace::omnitrace-user-library ALIAS omnitrace-user-library)
|
||||
|
||||
target_sources(
|
||||
omnitrace-user-library PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/user.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h)
|
||||
target_include_directories(
|
||||
omnitrace-user-library PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
||||
|
||||
check_cxx_compiler_flag("-fno-exceptions" omnitrace_user_library_fno_exceptions)
|
||||
check_cxx_compiler_flag("-ftls-model=local-dynamic"
|
||||
omnitrace_user_library_ftls_module_local_dynamic)
|
||||
|
||||
if(OMNITRACE_BUILD_DEVELOPER)
|
||||
if(omnitrace_user_library_fno_exceptions)
|
||||
target_compile_options(omnitrace-user-library PRIVATE -fno-exceptions)
|
||||
endif()
|
||||
|
||||
if(omnitrace_user_library_ftls_module_local_dynamic)
|
||||
target_compile_options(omnitrace-user-library PRIVATE -ftls-model=local-dynamic)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_target_properties(
|
||||
omnitrace-user-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace-user
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
BUILD_RPATH "\$ORIGIN"
|
||||
INSTALL_RPATH "\$ORIGIN")
|
||||
|
||||
install(
|
||||
TARGETS omnitrace-user-library
|
||||
EXPORT omnitrace-user-library-targets
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OPTIONAL)
|
||||
|
||||
install(
|
||||
FILES ${CMAKE_CURRENT_SOURCE_DIR}/omnitrace/user.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/omnitrace
|
||||
OPTIONAL)
|
||||
|
||||
install(
|
||||
EXPORT omnitrace-user-library-targets
|
||||
FILE omnitrace-user-library-targets.cmake
|
||||
NAMESPACE omnitrace::
|
||||
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/cmake/omnitrace)
|
||||
@@ -0,0 +1,50 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#ifndef OMNITRACE_USER_H_
|
||||
#define OMNITRACE_USER_H_ 1
|
||||
|
||||
#define OMNITRACE_ATTRIBUTE(...) __attribute__((__VA_ARGS__))
|
||||
#define OMNITRACE_VISIBILITY(MODE) OMNITRACE_ATTRIBUTE(visibility(MODE))
|
||||
#define OMNITRACE_PUBLIC_API OMNITRACE_VISIBILITY("default")
|
||||
#define OMNITRACE_HIDDEN_API OMNITRACE_VISIBILITY("hidden")
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
extern void omnitrace_user_start_trace(void) OMNITRACE_PUBLIC_API;
|
||||
extern void omnitrace_user_stop_trace(void) OMNITRACE_PUBLIC_API;
|
||||
extern void omnitrace_user_start_thread_trace(void) OMNITRACE_PUBLIC_API;
|
||||
extern void omnitrace_user_stop_thread_trace(void) OMNITRACE_PUBLIC_API;
|
||||
extern void omnitrace_user_push_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
extern void omnitrace_user_pop_region(const char*) OMNITRACE_PUBLIC_API;
|
||||
|
||||
extern void omnitrace_user_configure(void (*)(void), void (*)(void), void (*)(void),
|
||||
void (*)(void), void (*)(const char*),
|
||||
void (*)(const char*)) OMNITRACE_PUBLIC_API;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OMNITRACE_USER_H_
|
||||
@@ -0,0 +1,84 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#define OMNITRACE_SOURCE 1
|
||||
|
||||
#include "omnitrace/user.h"
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
namespace
|
||||
{
|
||||
using void_func_t = void (*)(void);
|
||||
using region_func_t = void (*)(const char*);
|
||||
|
||||
void_func_t _start_trace = nullptr;
|
||||
void_func_t _stop_trace = nullptr;
|
||||
void_func_t _start_thread_trace = nullptr;
|
||||
void_func_t _stop_thread_trace = nullptr;
|
||||
region_func_t _push_region = nullptr;
|
||||
region_func_t _pop_region = nullptr;
|
||||
} // namespace
|
||||
|
||||
extern "C"
|
||||
{
|
||||
void omnitrace_user_start_trace(void)
|
||||
{
|
||||
if(_start_trace) (*_start_trace)();
|
||||
}
|
||||
|
||||
void omnitrace_user_stop_trace(void)
|
||||
{
|
||||
if(_stop_trace) (*_stop_trace)();
|
||||
}
|
||||
|
||||
void omnitrace_user_start_thread_trace(void)
|
||||
{
|
||||
if(_start_thread_trace) (*_start_thread_trace)();
|
||||
}
|
||||
|
||||
void omnitrace_user_stop_thread_trace(void)
|
||||
{
|
||||
if(_stop_thread_trace) (*_stop_thread_trace)();
|
||||
}
|
||||
|
||||
void omnitrace_user_push_region(const char* name)
|
||||
{
|
||||
if(_push_region) (*_push_region)(name);
|
||||
}
|
||||
|
||||
void omnitrace_user_pop_region(const char* name)
|
||||
{
|
||||
if(_pop_region) (*_pop_region)(name);
|
||||
}
|
||||
|
||||
void omnitrace_user_configure(void (*_a)(), void (*_b)(), void (*_c)(), void (*_d)(),
|
||||
void (*_e)(const char*), void (*_f)(const char*))
|
||||
{
|
||||
_start_trace = _a;
|
||||
_stop_trace = _b;
|
||||
_start_thread_trace = _c;
|
||||
_stop_thread_trace = _d;
|
||||
_push_region = _e;
|
||||
_pop_region = _f;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace interface library
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
add_library(omnitrace-interface-library INTERFACE)
|
||||
add_library(omnitrace::omnitrace-interface-library ALIAS omnitrace-interface-library)
|
||||
|
||||
target_include_directories(
|
||||
omnitrace-interface-library INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}/include
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include)
|
||||
target_include_directories(omnitrace-interface-library SYSTEM
|
||||
INTERFACE ${perfetto_DIR}/sdk)
|
||||
|
||||
target_compile_definitions(
|
||||
omnitrace-interface-library
|
||||
INTERFACE OMNITRACE_MAX_THREADS=${OMNITRACE_MAX_THREADS}
|
||||
$<IF:$<BOOL:${OMNITRACE_CUSTOM_DATA_SOURCE}>,CUSTOM_DATA_SOURCE,>)
|
||||
|
||||
target_link_libraries(
|
||||
omnitrace-interface-library
|
||||
INTERFACE $<BUILD_INTERFACE:omnitrace::omnitrace-headers>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-threading>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-compile-options>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-hip>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-roctracer>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-rocm-smi>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-mpi>
|
||||
$<BUILD_INTERFACE:omnitrace::omnitrace-ptl>
|
||||
$<BUILD_INTERFACE:timemory::timemory-headers>
|
||||
$<BUILD_INTERFACE:timemory::timemory-gotcha>
|
||||
$<BUILD_INTERFACE:timemory::timemory-cxx-static>
|
||||
$<IF:$<BOOL:${OMNITRACE_USE_SANITIZER}>,omnitrace::omnitrace-sanitizer,>)
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace object library
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
add_library(omnitrace-object-library OBJECT)
|
||||
add_library(omnitrace::omnitrace-object-library ALIAS omnitrace-object-library)
|
||||
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/include/library/defines.hpp.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/include/library/defines.hpp @ONLY)
|
||||
|
||||
set(library_sources
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/api.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/config.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/cpu_freq.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/critical_trace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/kokkosp.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/gpu.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/ompt.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/perfetto.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/ptl.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/sampling.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/state.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_data.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/thread_sampler.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/timemory.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/backtrace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/fork_gotcha.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/mpi_gotcha.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/omnitrace.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/pthread_gotcha.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/user_region.cpp
|
||||
${perfetto_DIR}/sdk/perfetto.cc)
|
||||
|
||||
set(library_headers
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/api.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/config.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/common.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/cpu_freq.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/critical_trace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/debug.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/gpu.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/ompt.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/perfetto.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/ptl.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/sampling.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/state.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_data.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/thread_sampler.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/timemory.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fwd.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/backtrace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/fork_gotcha.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/functors.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/mpi_gotcha.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/omnitrace.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/rocm_smi.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/roctracer_callbacks.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/pthread_gotcha.hpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/include/library/components/user_region.hpp
|
||||
${perfetto_DIR}/sdk/perfetto.h)
|
||||
|
||||
target_sources(omnitrace-object-library PRIVATE ${library_sources} ${library_headers})
|
||||
|
||||
if(OMNITRACE_USE_ROCTRACER)
|
||||
target_sources(
|
||||
omnitrace-object-library
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer.cpp
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/library/components/roctracer_callbacks.cpp)
|
||||
endif()
|
||||
|
||||
if(OMNITRACE_USE_ROCM_SMI)
|
||||
target_sources(omnitrace-object-library
|
||||
PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/library/components/rocm_smi.cpp)
|
||||
endif()
|
||||
|
||||
target_link_libraries(omnitrace-object-library PRIVATE omnitrace-interface-library)
|
||||
|
||||
if(OMNITRACE_DYNINST_API_RT)
|
||||
get_filename_component(OMNITRACE_DYNINST_API_RT_DIR "${OMNITRACE_DYNINST_API_RT}"
|
||||
DIRECTORY)
|
||||
endif()
|
||||
|
||||
# ------------------------------------------------------------------------------#
|
||||
#
|
||||
# omnitrace shared library
|
||||
#
|
||||
# ------------------------------------------------------------------------------#
|
||||
|
||||
add_library(omnitrace-library SHARED $<TARGET_OBJECTS:omnitrace-object-library>)
|
||||
add_library(omnitrace::omnitrace-library ALIAS omnitrace-library)
|
||||
|
||||
target_link_libraries(omnitrace-library PRIVATE omnitrace-interface-library)
|
||||
|
||||
set_target_properties(
|
||||
omnitrace-library
|
||||
PROPERTIES OUTPUT_NAME omnitrace
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
INSTALL_RPATH
|
||||
"\$ORIGIN:\$ORIGIN/timemory/libunwind:\$ORIGIN/dyninst-tpls/libs")
|
||||
|
||||
install(
|
||||
TARGETS omnitrace-library
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OPTIONAL)
|
||||
@@ -51,6 +51,12 @@ extern "C"
|
||||
/// stops an instrumentation region
|
||||
void omnitrace_pop_trace(const char* name) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// starts an instrumentation region (user-defined)
|
||||
void omnitrace_push_region(const char* name) OMNITRACE_PUBLIC_API;
|
||||
|
||||
/// stops an instrumentation region (user-defined)
|
||||
void omnitrace_pop_region(const char* name) OMNITRACE_PUBLIC_API;
|
||||
|
||||
// these are the real implementations for internal calling convention
|
||||
void omnitrace_init_library_hidden(void) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_init_hidden(const char*, bool, const char*) OMNITRACE_HIDDEN_API;
|
||||
@@ -60,4 +66,6 @@ extern "C"
|
||||
void omnitrace_set_mpi_hidden(bool use, bool attached) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_push_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_pop_trace_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_push_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
void omnitrace_pop_region_hidden(const char* name) OMNITRACE_HIDDEN_API;
|
||||
}
|
||||
+14
@@ -68,6 +68,7 @@ using functor_t = std::function<void(Tp...)>;
|
||||
using default_functor_t = functor_t<const char*>;
|
||||
|
||||
struct omnitrace;
|
||||
struct user_region;
|
||||
struct backtrace;
|
||||
struct backtrace_wall_clock
|
||||
{};
|
||||
@@ -126,6 +127,8 @@ TIMEMORY_DEFINE_CONCRETE_TRAIT(is_available, omnitrace::component::sampling_gpu_
|
||||
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::omnitrace, project::omnitrace,
|
||||
category::dynamic_instrumentation, os::supports_linux)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::user_region, project::omnitrace,
|
||||
os::supports_linux)
|
||||
TIMEMORY_SET_COMPONENT_API(omnitrace::component::roctracer, project::omnitrace,
|
||||
tpls::rocm, device::gpu, os::supports_linux,
|
||||
category::external)
|
||||
@@ -154,6 +157,8 @@ TIMEMORY_SET_COMPONENT_API(omnitrace::component::sampling_gpu_temp, project::omn
|
||||
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::omnitrace, OMNITRACE_COMPONENT,
|
||||
"omnitrace", "omnitrace_component")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::user_region, OMNITRACE_USER_REGION,
|
||||
"user_region", "omnitrace_user_region")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::roctracer, OMNITRACE_ROCTRACER,
|
||||
"roctracer", "omnitrace_roctracer")
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
|
||||
@@ -173,6 +178,15 @@ TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_power,
|
||||
TIMEMORY_PROPERTY_SPECIALIZATION(omnitrace::component::sampling_gpu_temp,
|
||||
OMNITRACE_SAMPLING_GPU_TEMP, "sampling_gpu_temp", "")
|
||||
|
||||
TIMEMORY_METADATA_SPECIALIZATION(
|
||||
omnitrace::component::omnitrace, "omnitrace",
|
||||
"Invokes instrumentation functions 'omnitrace_push_trace' and 'omnitrace_pop_trace'",
|
||||
"Used by gotcha wrappers")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(
|
||||
omnitrace::component::user_region, "user_region",
|
||||
"Invokes instrumentation functions 'omnitrace_user_push_region' and "
|
||||
"'omnitrace_user_pop_region'",
|
||||
"Used by OMPT")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::roctracer, "roctracer",
|
||||
"High-precision ROCm API and kernel tracing", "")
|
||||
TIMEMORY_METADATA_SPECIALIZATION(omnitrace::component::sampling_wall_clock,
|
||||
@@ -43,8 +43,3 @@ private:
|
||||
};
|
||||
} // namespace component
|
||||
} // namespace omnitrace
|
||||
|
||||
TIMEMORY_METADATA_SPECIALIZATION(
|
||||
omnitrace::component::omnitrace, "omnitrace",
|
||||
"Invokes instrumentation functions 'omnitrace_push_trace' and 'omnitrace_pop_trace'",
|
||||
"Used by gotcha wrappers")
|
||||
@@ -0,0 +1,56 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "library/defines.hpp"
|
||||
#include "library/timemory.hpp"
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace component
|
||||
{
|
||||
// timemory component which calls omnitrace functions
|
||||
// (used in gotcha wrappers)
|
||||
struct user_region : comp::base<user_region, void>
|
||||
{
|
||||
static std::string label() { return "user_region"; }
|
||||
void start();
|
||||
void stop();
|
||||
void set_prefix(const char*);
|
||||
|
||||
private:
|
||||
const char* m_prefix = nullptr;
|
||||
};
|
||||
} // namespace component
|
||||
} // namespace omnitrace
|
||||
|
||||
TIMEMORY_COMPONENT_ALIAS(omnitrace_user_region, omnitrace::component::user_region)
|
||||
|
||||
#if !defined(OMNITRACE_EXTERN_COMPONENTS) || \
|
||||
(defined(OMNITRACE_EXTERN_COMPONENTS) && OMNITRACE_EXTERN_COMPONENTS > 0)
|
||||
|
||||
# include <timemory/operations.hpp>
|
||||
|
||||
TIMEMORY_DECLARE_EXTERN_COMPONENT(omnitrace_user_region, false, void)
|
||||
|
||||
#endif
|
||||
@@ -171,6 +171,9 @@ get_use_critical_trace();
|
||||
bool
|
||||
get_use_kokkosp();
|
||||
|
||||
bool
|
||||
get_use_ompt();
|
||||
|
||||
bool
|
||||
get_timeline_sampling();
|
||||
|
||||
@@ -245,6 +248,9 @@ get_critical_trace_per_row();
|
||||
State&
|
||||
get_state();
|
||||
|
||||
/// returns old state
|
||||
State set_state(State);
|
||||
|
||||
std::unique_ptr<main_bundle_t>&
|
||||
get_main_bundle();
|
||||
|
||||
+60
-4
@@ -30,6 +30,9 @@
|
||||
#include <timemory/utility/utility.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
@@ -47,8 +50,32 @@ get_debug_pid();
|
||||
bool
|
||||
get_critical_trace_debug();
|
||||
} // namespace config
|
||||
|
||||
namespace debug
|
||||
{
|
||||
namespace
|
||||
{
|
||||
template <typename T, size_t... Idx>
|
||||
auto get_chars(std::index_sequence<Idx...>)
|
||||
{
|
||||
static const char _v[sizeof...(Idx) + 1] = { T::get()[Idx]..., '\0' };
|
||||
return _v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
auto
|
||||
get_chars()
|
||||
{
|
||||
return get_chars<T>(typename T::sequence{});
|
||||
}
|
||||
} // namespace
|
||||
} // namespace debug
|
||||
} // namespace omnitrace
|
||||
|
||||
#define OMNITRACE_VAR_NAME_COMBINE(X, Y) X##Y
|
||||
#define OMNITRACE_LINESTR TIMEMORY_STRINGIZE(__LINE__)
|
||||
#define OMNITRACE_VARIABLE(LABEL) OMNITRACE_VAR_NAME_COMBINE(_omni_var_, LABEL)
|
||||
|
||||
#if defined(TIMEMORY_USE_MPI)
|
||||
# define OMNITRACE_PROCESS_IDENTIFIER static_cast<int>(::tim::dmp::rank())
|
||||
#elif defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
@@ -59,6 +86,26 @@ get_critical_trace_debug();
|
||||
# define OMNITRACE_PROCESS_IDENTIFIER static_cast<int>(::tim::process::get_id())
|
||||
#endif
|
||||
|
||||
#define OMNITRACE_FUNCTION \
|
||||
std::string{ __FUNCTION__ } \
|
||||
.substr(0, std::string_view{ __FUNCTION__ }.find("_hidden")) \
|
||||
.c_str()
|
||||
|
||||
#define OMNITRACE_CT_FUNCTION(VAR, STR) \
|
||||
static constexpr auto OMNITRACE_VARIABLE(__LINE__) = std::string_view{ STR }; \
|
||||
VAR = OMNITRACE_CT_FUNCTION_IMPL(OMNITRACE_VARIABLE(__LINE__));
|
||||
|
||||
#define OMNITRACE_CT_FUNCTION_IMPL(STR) \
|
||||
[]() { \
|
||||
struct wrapper \
|
||||
{ \
|
||||
static constexpr const char* get() { return STR.data(); } \
|
||||
using sequence = \
|
||||
std::make_index_sequence<std::min(STR.find("_hidden"), STR.length())>; \
|
||||
}; \
|
||||
return ::omnitrace::debug::get_chars<wrapper>(); \
|
||||
}();
|
||||
|
||||
#define OMNITRACE_CONDITIONAL_PRINT(COND, ...) \
|
||||
if((COND) && ::omnitrace::config::get_debug_tid() && \
|
||||
::omnitrace::config::get_debug_pid()) \
|
||||
@@ -89,7 +136,7 @@ get_critical_trace_debug();
|
||||
fflush(stderr); \
|
||||
tim::auto_lock_t _lk{ tim::type_mutex<decltype(std::cerr)>() }; \
|
||||
fprintf(stderr, "[omnitrace][%i][%li][%s] ", OMNITRACE_PROCESS_IDENTIFIER, \
|
||||
tim::threading::get_id(), __FUNCTION__); \
|
||||
tim::threading::get_id(), OMNITRACE_FUNCTION); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
}
|
||||
@@ -100,7 +147,7 @@ get_critical_trace_debug();
|
||||
{ \
|
||||
fflush(stderr); \
|
||||
tim::auto_lock_t _lk{ tim::type_mutex<decltype(std::cerr)>() }; \
|
||||
fprintf(stderr, "[omnitrace][%s] ", __FUNCTION__); \
|
||||
fprintf(stderr, "[omnitrace][%s] ", OMNITRACE_FUNCTION); \
|
||||
fprintf(stderr, __VA_ARGS__); \
|
||||
fflush(stderr); \
|
||||
}
|
||||
@@ -110,7 +157,8 @@ get_critical_trace_debug();
|
||||
{ \
|
||||
char _msg_buffer[2048]; \
|
||||
snprintf(_msg_buffer, 2048, "[omnitrace][%i][%li][%s] ", \
|
||||
OMNITRACE_PROCESS_IDENTIFIER, tim::threading::get_id(), __FUNCTION__); \
|
||||
OMNITRACE_PROCESS_IDENTIFIER, tim::threading::get_id(), \
|
||||
OMNITRACE_FUNCTION); \
|
||||
auto len = strlen(_msg_buffer); \
|
||||
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
|
||||
throw std::runtime_error(_msg_buffer); \
|
||||
@@ -120,12 +168,20 @@ get_critical_trace_debug();
|
||||
if(COND) \
|
||||
{ \
|
||||
char _msg_buffer[2048]; \
|
||||
snprintf(_msg_buffer, 2048, "[omnitrace][%s] ", __FUNCTION__); \
|
||||
snprintf(_msg_buffer, 2048, "[omnitrace][%s] ", OMNITRACE_FUNCTION); \
|
||||
auto len = strlen(_msg_buffer); \
|
||||
snprintf(_msg_buffer + len, 2048 - len, __VA_ARGS__); \
|
||||
throw std::runtime_error(_msg_buffer); \
|
||||
}
|
||||
|
||||
#define OMNITRACE_CI_THROW(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_THROW(::omnitrace::get_is_continuous_integration() && (COND), \
|
||||
__VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_CI_BASIC_THROW(COND, ...) \
|
||||
OMNITRACE_CONDITIONAL_BASIC_THROW( \
|
||||
::omnitrace::get_is_continuous_integration() && (COND), __VA_ARGS__)
|
||||
|
||||
#define OMNITRACE_STRINGIZE(...) #__VA_ARGS__
|
||||
#define OMNITRACE_ESC(...) __VA_ARGS__
|
||||
|
||||
+6
-4
@@ -36,12 +36,14 @@
|
||||
// clang-format on
|
||||
|
||||
#define TIMEMORY_USER_COMPONENT_ENUM \
|
||||
OMNITRACE_COMPONENT_idx, OMNITRACE_ROCTRACER_idx, OMNITRACE_SAMPLING_WALL_CLOCK_idx, \
|
||||
OMNITRACE_SAMPLING_CPU_CLOCK_idx, OMNITRACE_SAMPLING_PERCENT_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_POWER_idx, OMNITRACE_SAMPLING_GPU_TEMP_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_BUSY_idx, OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
|
||||
OMNITRACE_COMPONENT_idx, OMNITRACE_USER_REGION_idx, OMNITRACE_ROCTRACER_idx, \
|
||||
OMNITRACE_SAMPLING_WALL_CLOCK_idx, OMNITRACE_SAMPLING_CPU_CLOCK_idx, \
|
||||
OMNITRACE_SAMPLING_PERCENT_idx, OMNITRACE_SAMPLING_GPU_POWER_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_TEMP_idx, OMNITRACE_SAMPLING_GPU_BUSY_idx, \
|
||||
OMNITRACE_SAMPLING_GPU_MEMORY_USAGE_idx,
|
||||
|
||||
#define OMNITRACE_COMPONENT OMNITRACE_COMPONENT_idx
|
||||
#define OMNITRACE_USER_REGION OMNITRACE_USER_REGION_idx
|
||||
#define OMNITRACE_ROCTRACER OMNITRACE_ROCTRACER_idx
|
||||
#define OMNITRACE_SAMPLING_WALL_CLOCK OMNITRACE_SAMPLING_WALL_CLOCK_idx
|
||||
#define OMNITRACE_SAMPLING_CPU_CLOCK OMNITRACE_SAMPLING_CPU_CLOCK_idx
|
||||
@@ -0,0 +1,35 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace ompt
|
||||
{
|
||||
void
|
||||
setup();
|
||||
|
||||
void
|
||||
shutdown();
|
||||
} // namespace ompt
|
||||
} // namespace omnitrace
|
||||
@@ -33,6 +33,7 @@
|
||||
# define PERFETTO_CATEGORIES \
|
||||
perfetto::Category("host").SetDescription("Host-side function tracing"), \
|
||||
perfetto::Category("device").SetDescription("Device-side function tracing"), \
|
||||
perfetto::Category("user").SetDescription("User-defined regions"), \
|
||||
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
|
||||
perfetto::Category("sampling") \
|
||||
.SetDescription("Metrics derived from sampling"), \
|
||||
@@ -46,6 +47,7 @@
|
||||
# define PERFETTO_CATEGORIES \
|
||||
perfetto::Category("host").SetDescription("Host-side function tracing"), \
|
||||
perfetto::Category("device").SetDescription("Device-side function tracing"), \
|
||||
perfetto::Category("user").SetDescription("User-defined regions"), \
|
||||
perfetto::Category("rocm_smi").SetDescription("Device-level metrics"), \
|
||||
perfetto::Category("sampling") \
|
||||
.SetDescription("Metrics derived from sampling"), \
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "library/debug.hpp"
|
||||
#include "library/defines.hpp"
|
||||
#include "library/gpu.hpp"
|
||||
#include "library/ompt.hpp"
|
||||
#include "library/ptl.hpp"
|
||||
#include "library/sampling.hpp"
|
||||
#include "library/thread_data.hpp"
|
||||
@@ -46,10 +47,22 @@ using namespace omnitrace;
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
using library_functors = omnitrace::component::functors<omnitrace::api::omnitrace>;
|
||||
namespace
|
||||
{
|
||||
struct omni_regions
|
||||
{};
|
||||
struct user_regions
|
||||
{};
|
||||
} // namespace
|
||||
|
||||
TIMEMORY_DEFINE_NAME_TRAIT("cpu_instrumentation", library_functors);
|
||||
TIMEMORY_INVOKE_PREINIT(library_functors)
|
||||
using omni_functors = omnitrace::component::functors<omni_regions>;
|
||||
using user_functors = omnitrace::component::functors<user_regions>;
|
||||
|
||||
// TIMEMORY_DEFINE_NAME_TRAIT("host", omni_functors);
|
||||
// TIMEMORY_DEFINE_NAME_TRAIT("user", user_functors);
|
||||
|
||||
TIMEMORY_INVOKE_PREINIT(omni_functors)
|
||||
TIMEMORY_INVOKE_PREINIT(user_functors)
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
@@ -159,6 +172,9 @@ pop_count()
|
||||
}
|
||||
|
||||
auto _debug_push = tim::get_env("OMNITRACE_DEBUG_PUSH", false) && !get_debug_env();
|
||||
auto _debug_pop = tim::get_env("OMNITRACE_DEBUG_POP", false) && !get_debug_env();
|
||||
auto _debug_user =
|
||||
tim::get_env("OMNITRACE_DEBUG_USER_REGIONS", false) && !get_debug_env();
|
||||
} // namespace
|
||||
|
||||
//======================================================================================//
|
||||
@@ -172,11 +188,11 @@ omnitrace_push_trace_hidden(const char* name)
|
||||
if(get_state() == State::Finalized)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
_debug_push, "%s(%s) called during finalization\n", __FUNCTION__, name);
|
||||
_debug_push, "omnitrace_push_trace(%s) called during finalization\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "%s(%s)\n", __FUNCTION__, name);
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "omnitrace_push_trace(%s)\n", name);
|
||||
|
||||
// the expectation here is that if the state is not active then the call
|
||||
// to omnitrace_init_tooling_hidden will activate all the appropriate
|
||||
@@ -184,12 +200,13 @@ omnitrace_push_trace_hidden(const char* name)
|
||||
if(get_state() != State::Active && !omnitrace_init_tooling_hidden())
|
||||
{
|
||||
static auto _debug = get_debug_env() || get_debug_init();
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug, "%s :: not active. state = %s\n",
|
||||
name, std::to_string(get_state()).c_str());
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
_debug, "omnitrace_push_trace(%s) ignored :: not active. state = %s\n", name,
|
||||
std::to_string(get_state()).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
OMNITRACE_DEBUG_F("%s\n", name);
|
||||
OMNITRACE_DEBUG("omnitrace_push_trace(%s)\n", name);
|
||||
|
||||
static auto _sample_rate = std::max<size_t>(get_instrumentation_interval(), 1);
|
||||
static thread_local size_t _sample_idx = 0;
|
||||
@@ -197,7 +214,7 @@ omnitrace_push_trace_hidden(const char* name)
|
||||
auto _enabled = (_sample_idx++ % _sample_rate == 0);
|
||||
|
||||
_interval->emplace_back(_enabled);
|
||||
if(_enabled) library_functors::start(name);
|
||||
if(_enabled) omni_functors::start(name);
|
||||
if(get_use_critical_trace())
|
||||
{
|
||||
uint64_t _cid = 0;
|
||||
@@ -222,15 +239,17 @@ omnitrace_pop_trace_hidden(const char* name)
|
||||
{
|
||||
++pop_count();
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_pop, "omnitrace_pop_trace(%s)\n", name);
|
||||
|
||||
// only execute when active
|
||||
if(get_state() == State::Active)
|
||||
{
|
||||
OMNITRACE_DEBUG_F("%s\n", name);
|
||||
OMNITRACE_DEBUG("omnitrace_pop_trace(%s)\n", name);
|
||||
|
||||
auto& _interval_data = get_interval_data();
|
||||
if(!_interval_data->empty())
|
||||
{
|
||||
if(_interval_data->back()) library_functors::stop(name);
|
||||
if(_interval_data->back()) omni_functors::stop(name);
|
||||
_interval_data->pop_back();
|
||||
}
|
||||
|
||||
@@ -255,9 +274,64 @@ omnitrace_pop_trace_hidden(const char* name)
|
||||
else
|
||||
{
|
||||
static auto _debug = get_debug_env();
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug, "[%s] %s ignored :: state = %s\n",
|
||||
__FUNCTION__, name,
|
||||
std::to_string(get_state()).c_str());
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
_debug, "omnitrace_pop_trace(%s) ignored :: state = %s\n", name,
|
||||
std::to_string(get_state()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
///
|
||||
///
|
||||
///
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_region_hidden(const char* name)
|
||||
{
|
||||
// unconditionally return if finalized
|
||||
if(get_state() == State::Finalized)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
_debug_user, "omnitrace_push_region(%s) called during finalization\n", name);
|
||||
return;
|
||||
}
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(_debug_push, "omnitrace_push_region(%s)\n", name);
|
||||
|
||||
// the expectation here is that if the state is not active then the call
|
||||
// to omnitrace_init_tooling_hidden will activate all the appropriate
|
||||
// tooling one time and as it exits set it to active and return true.
|
||||
if(get_state() != State::Active && !omnitrace_init_tooling_hidden())
|
||||
{
|
||||
static auto _debug = get_debug_env() || get_debug_init();
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
_debug, "omnitrace_push_region(%s) ignored :: not active. state = %s\n", name,
|
||||
std::to_string(get_state()).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
OMNITRACE_DEBUG("omnitrace_push_region(%s)\n", name);
|
||||
user_functors::start(name);
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_region_hidden(const char* name)
|
||||
{
|
||||
// only execute when active
|
||||
if(get_state() == State::Active)
|
||||
{
|
||||
OMNITRACE_DEBUG("omnitrace_pop_region(%s)\n", name);
|
||||
user_functors::stop(name);
|
||||
}
|
||||
else
|
||||
{
|
||||
static auto _debug = get_debug_env();
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
_debug, "omnitrace_pop_region(%s) ignored :: state = %s\n", name,
|
||||
std::to_string(get_state()).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +345,7 @@ extern "C" void
|
||||
omnitrace_set_env_hidden(const char* env_name, const char* env_val)
|
||||
{
|
||||
// just search env to avoid initializing the settings
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_init() || get_verbose_env() > 2,
|
||||
"[%s] Setting env: %s=%s\n", __FUNCTION__, env_name,
|
||||
env_val);
|
||||
|
||||
@@ -279,9 +353,10 @@ omnitrace_set_env_hidden(const char* env_name, const char* env_val)
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
get_state() >= State::Init &&
|
||||
(config::get_is_continuous_integration() || get_debug_env()),
|
||||
"%s(\"%s\", \"%s\") called after omnitrace was initialized. state = %s",
|
||||
__FUNCTION__, env_name, env_val, std::to_string(get_state()).c_str());
|
||||
(config::get_is_continuous_integration() || get_debug_init()),
|
||||
"omnitrace_set_env(\"%s\", \"%s\") called after omnitrace was initialized. state "
|
||||
"= %s",
|
||||
env_name, env_val, std::to_string(get_state()).c_str());
|
||||
}
|
||||
|
||||
//======================================================================================//
|
||||
@@ -300,7 +375,7 @@ extern "C" void
|
||||
omnitrace_set_mpi_hidden(bool use, bool attached)
|
||||
{
|
||||
// just search env to avoid initializing the settings
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_env() || get_verbose_env() > 2,
|
||||
OMNITRACE_CONDITIONAL_PRINT(get_debug_init() || get_verbose_env() > 2,
|
||||
"[%s] use: %s, attached: %s\n", __FUNCTION__,
|
||||
(use) ? "y" : "n", (attached) ? "y" : "n");
|
||||
|
||||
@@ -319,9 +394,10 @@ omnitrace_set_mpi_hidden(bool use, bool attached)
|
||||
|
||||
OMNITRACE_CONDITIONAL_THROW(
|
||||
get_state() >= State::Init &&
|
||||
(config::get_is_continuous_integration() || get_debug_env()),
|
||||
"%s(use=%s, attached=%s) called after omnitrace was initialized. state = %s",
|
||||
__FUNCTION__, std::to_string(use).c_str(), std::to_string(attached).c_str(),
|
||||
(config::get_is_continuous_integration() || get_debug_init()),
|
||||
"omnitrace_set_mpi(use=%s, attached=%s) called after omnitrace was initialized. "
|
||||
"state = %s",
|
||||
std::to_string(use).c_str(), std::to_string(attached).c_str(),
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
_start_gotcha_callback();
|
||||
@@ -335,23 +411,37 @@ omnitrace_init_library_hidden()
|
||||
auto _tid = threading::get_id();
|
||||
(void) _tid;
|
||||
|
||||
auto _mode = get_mode();
|
||||
auto _debug_init = get_debug_init();
|
||||
static bool _once = false;
|
||||
auto _mode = get_mode();
|
||||
auto _debug_init = get_debug_init();
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s...\n",
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
OMNITRACE_CI_THROW(get_state() != State::PreInit, "State is not PreInit :: %s",
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
if(get_state() != State::PreInit || get_state() == State::Init || _once) return;
|
||||
_once = true;
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "State is %s. Setting to %s...\n",
|
||||
std::to_string(get_state()).c_str(),
|
||||
std::to_string(State::Init).c_str());
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(
|
||||
_debug_init, "Calling backtrace once so that the one-time call of malloc in "
|
||||
"glibc's backtrace() occurs...\n");
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(
|
||||
_debug_init, "Calling backtrace once so that the one-time call of malloc in "
|
||||
"glibc's backtrace() occurs...\n");
|
||||
std::stringstream _ss{};
|
||||
tim::print_backtrace<64>(_ss);
|
||||
(void) _ss;
|
||||
}
|
||||
|
||||
get_state() = State::Init;
|
||||
set_state(State::Init);
|
||||
|
||||
OMNITRACE_CI_THROW(get_state() != State::Init,
|
||||
"set_state(State::Init) failed. state is %s",
|
||||
std::to_string(get_state()).c_str());
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT_F(_debug_init, "Configuring settings...\n");
|
||||
|
||||
@@ -395,8 +485,9 @@ omnitrace_init_library_hidden()
|
||||
|
||||
if(get_use_kokkosp())
|
||||
{
|
||||
auto _force = 0;
|
||||
if(tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY") == "libtimemory.so")
|
||||
auto _force = 0;
|
||||
auto _current_kokkosp_lib = tim::get_env<std::string>("KOKKOS_PROFILE_LIBRARY");
|
||||
if(std::regex_search(_current_kokkosp_lib, std::regex{ "libtimemory\\." }))
|
||||
_force = 1;
|
||||
tim::set_env("KOKKOS_PROFILE_LIBRARY", "libomnitrace.so", _force);
|
||||
}
|
||||
@@ -537,8 +628,12 @@ omnitrace_init_tooling_hidden()
|
||||
return true;
|
||||
}();
|
||||
static thread_local auto _dtor = scope::destructor{ []() {
|
||||
if(get_use_sampling()) sampling::shutdown();
|
||||
thread_data<omnitrace_thread_bundle_t>::instance()->stop();
|
||||
if(get_state() != State::Finalized)
|
||||
{
|
||||
if(get_use_sampling()) sampling::shutdown();
|
||||
if(thread_data<omnitrace_thread_bundle_t>::instance())
|
||||
thread_data<omnitrace_thread_bundle_t>::instance()->stop();
|
||||
}
|
||||
} };
|
||||
(void) _thread_setup;
|
||||
(void) _dtor;
|
||||
@@ -555,7 +650,7 @@ omnitrace_init_tooling_hidden()
|
||||
(void) _v;
|
||||
};
|
||||
|
||||
// functors for starting and stopping timemory
|
||||
// functors for starting and stopping timemory omni functors
|
||||
auto _push_timemory = [](const char* name) {
|
||||
auto& _data = get_instrumentation_bundles();
|
||||
// this generates a hash for the raw string array
|
||||
@@ -566,11 +661,6 @@ omnitrace_init_tooling_hidden()
|
||||
_bundle->start();
|
||||
};
|
||||
|
||||
auto _push_perfetto = [](const char* name) {
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_BEGIN("host", perfetto::StaticString(name), _ts);
|
||||
};
|
||||
|
||||
auto _pop_timemory = [](const char* name) {
|
||||
auto _hash = tim::hash::get_hash_id(tim::string_view_t{ name });
|
||||
auto& _data = get_instrumentation_bundles();
|
||||
@@ -593,14 +683,33 @@ omnitrace_init_tooling_hidden()
|
||||
}
|
||||
};
|
||||
|
||||
// functors for starting and stopping perfetto omni functors
|
||||
auto _push_perfetto = [](const char* name) {
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_BEGIN("host", perfetto::StaticString(name), _ts);
|
||||
};
|
||||
|
||||
auto _pop_perfetto = [](const char*) {
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_END("host", _ts);
|
||||
};
|
||||
|
||||
// functors for starting and stopping perfetto user functors
|
||||
auto _push_user_perfetto = [](const char* name) {
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_BEGIN("user", nullptr, _ts, [name](perfetto::EventContext& _ctx) {
|
||||
_ctx.event()->set_name(name);
|
||||
});
|
||||
};
|
||||
|
||||
auto _pop_user_perfetto = [](const char*) {
|
||||
uint64_t _ts = comp::wall_clock::record();
|
||||
TRACE_EVENT_END("user", _ts);
|
||||
};
|
||||
|
||||
if(get_use_perfetto() && get_use_timemory())
|
||||
{
|
||||
library_functors::configure(
|
||||
omni_functors::configure(
|
||||
[=](const char* name) {
|
||||
_thread_init();
|
||||
_push_perfetto(name);
|
||||
@@ -611,20 +720,44 @@ omnitrace_init_tooling_hidden()
|
||||
_pop_timemory(name);
|
||||
_pop_perfetto(name);
|
||||
});
|
||||
user_functors::configure(
|
||||
[=](const char* name) {
|
||||
_thread_init();
|
||||
_push_user_perfetto(name);
|
||||
_push_timemory(name);
|
||||
},
|
||||
[=](const char* name) {
|
||||
_pop_timemory(name);
|
||||
_pop_user_perfetto(name);
|
||||
});
|
||||
}
|
||||
else if(get_use_perfetto())
|
||||
{
|
||||
library_functors::configure(
|
||||
omni_functors::configure(
|
||||
[=](const char* name) {
|
||||
_thread_init();
|
||||
_push_perfetto(name);
|
||||
_setup_thread_sampling();
|
||||
},
|
||||
[=](const char* name) { _pop_perfetto(name); });
|
||||
user_functors::configure(
|
||||
[=](const char* name) {
|
||||
_thread_init();
|
||||
_push_user_perfetto(name);
|
||||
_setup_thread_sampling();
|
||||
},
|
||||
[=](const char* name) { _pop_user_perfetto(name); });
|
||||
}
|
||||
else if(get_use_timemory())
|
||||
{
|
||||
library_functors::configure(
|
||||
omni_functors::configure(
|
||||
[=](const char* name) {
|
||||
_thread_init();
|
||||
_push_timemory(name);
|
||||
_setup_thread_sampling();
|
||||
},
|
||||
[=](const char* name) { _pop_timemory(name); });
|
||||
user_functors::configure(
|
||||
[=](const char* name) {
|
||||
_thread_init();
|
||||
_push_timemory(name);
|
||||
@@ -633,6 +766,8 @@ omnitrace_init_tooling_hidden()
|
||||
[=](const char* name) { _pop_timemory(name); });
|
||||
}
|
||||
|
||||
ompt::setup();
|
||||
|
||||
if(get_use_perfetto() && !is_system_backend())
|
||||
{
|
||||
#if defined(CUSTOM_DATA_SOURCE)
|
||||
@@ -676,9 +811,16 @@ omnitrace_init_hidden(const char* _mode, bool _is_binary_rewrite, const char* _a
|
||||
(void) pop_count();
|
||||
|
||||
get_finalization_functions().emplace_back([_argv0]() {
|
||||
// if main hasn't been popped yet, pop it
|
||||
OMNITRACE_BASIC_PRINT("Running omnitrace_pop_trace(%s)...\n", _argv0);
|
||||
omnitrace_pop_trace_hidden(_argv0);
|
||||
OMNITRACE_CI_THROW(get_state() != State::Active,
|
||||
"Finalizer function for popping main invoked in non-active "
|
||||
"state :: state = %s\n",
|
||||
std::to_string(get_state()).c_str());
|
||||
if(get_state() == State::Active)
|
||||
{
|
||||
// if main hasn't been popped yet, pop it
|
||||
OMNITRACE_BASIC_VERBOSE(2, "Running omnitrace_pop_trace(%s)...\n", _argv0);
|
||||
omnitrace_pop_trace_hidden(_argv0);
|
||||
}
|
||||
});
|
||||
|
||||
std::atexit([]() {
|
||||
@@ -740,9 +882,10 @@ omnitrace_finalize_hidden(void)
|
||||
}
|
||||
}
|
||||
|
||||
get_state() = State::Finalized;
|
||||
set_state(State::Finalized);
|
||||
|
||||
library_functors::configure([](const char*) {}, [](const char*) {});
|
||||
omni_functors::configure([](const char*) {}, [](const char*) {});
|
||||
user_functors::configure([](const char*) {}, [](const char*) {});
|
||||
|
||||
pthread_gotcha::push_enable_sampling_on_child_threads(false);
|
||||
pthread_gotcha::set_sampling_on_all_future_threads(false);
|
||||
@@ -785,6 +928,8 @@ omnitrace_finalize_hidden(void)
|
||||
}
|
||||
}
|
||||
|
||||
ompt::shutdown();
|
||||
|
||||
OMNITRACE_DEBUG_F("Stopping and destroying instrumentation bundles...\n");
|
||||
for(auto& itr : instrumentation_bundles::instances())
|
||||
{
|
||||
@@ -34,6 +34,18 @@ omnitrace_pop_trace(const char* _name)
|
||||
omnitrace_pop_trace_hidden(_name);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_push_region(const char* _name)
|
||||
{
|
||||
omnitrace_push_region_hidden(_name);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_pop_region(const char* _name)
|
||||
{
|
||||
omnitrace_pop_region_hidden(_name);
|
||||
}
|
||||
|
||||
extern "C" void
|
||||
omnitrace_init_library(void)
|
||||
{
|
||||
+4
-2
@@ -231,7 +231,7 @@ backtrace::get_thread_cpu_timestamp() const
|
||||
void
|
||||
backtrace::sample(int signum)
|
||||
{
|
||||
if(get_state() != State::Active)
|
||||
if(signum != -1 && get_state() != State::Active)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_PRINT(
|
||||
get_debug_sampling(),
|
||||
@@ -341,7 +341,6 @@ backtrace::configure(bool _setup, int64_t _tid)
|
||||
|
||||
OMNITRACE_DEBUG("Configuring sampler for thread %lu...\n", _tid);
|
||||
sampler_running_instances::construct(true);
|
||||
backtrace_init_instances::construct();
|
||||
sampling::sampler_instances::construct("omnitrace", _tid, *_signal_types);
|
||||
_sampler->set_signals(*_signal_types);
|
||||
_sampler->set_flags(SA_RESTART);
|
||||
@@ -363,6 +362,7 @@ backtrace::configure(bool _setup, int64_t _tid)
|
||||
_sampler->get_rate(units::sec));
|
||||
|
||||
// (void) sampling::sampler_t::get_samplers(_tid);
|
||||
backtrace_init_instances::construct();
|
||||
get_backtrace_init(_tid)->sample();
|
||||
_sampler->configure(false);
|
||||
_sampler->start();
|
||||
@@ -617,6 +617,8 @@ backtrace::post_process(int64_t _tid)
|
||||
|
||||
auto* _bt = ditr->get<backtrace>();
|
||||
|
||||
if(_bt->m_ts < _last_wall_ts) continue;
|
||||
|
||||
double _elapsed_wc = (_bt->m_ts - _last_wall_ts).count();
|
||||
double _elapsed_cc = (_bt->m_thr_cpu_ts - _last_cpu_ts);
|
||||
|
||||
+3
-4
@@ -86,8 +86,7 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***)
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(), "[%s] %s(int*, char***)\n",
|
||||
__FUNCTION__, _data.tool_id.c_str());
|
||||
|
||||
if(get_state() == ::omnitrace::State::DelayedInit)
|
||||
get_state() = ::omnitrace::State::PreInit;
|
||||
if(get_state() < ::omnitrace::State::Init) set_state(::omnitrace::State::PreInit);
|
||||
|
||||
omnitrace_push_trace_hidden(_data.tool_id.c_str());
|
||||
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
@@ -102,8 +101,8 @@ mpi_gotcha::audit(const gotcha_data_t& _data, audit::incoming, int*, char***, in
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug_env(),
|
||||
"[%s] %s(int*, char***, int, int*)\n", __FUNCTION__,
|
||||
_data.tool_id.c_str());
|
||||
if(get_state() == ::omnitrace::State::DelayedInit)
|
||||
get_state() = ::omnitrace::State::PreInit;
|
||||
|
||||
if(get_state() < ::omnitrace::State::Init) set_state(::omnitrace::State::PreInit);
|
||||
|
||||
omnitrace_push_trace_hidden(_data.tool_id.c_str());
|
||||
#if !defined(TIMEMORY_USE_MPI) && defined(TIMEMORY_USE_MPI_HEADERS)
|
||||
@@ -140,6 +140,8 @@ pthread_gotcha::wrapper::operator()() const
|
||||
{
|
||||
_tid = threading::get_id();
|
||||
threading::set_thread_name(TIMEMORY_JOIN(" ", "Thread", _tid).c_str());
|
||||
// initialize thread-local statics
|
||||
(void) tim::get_unw_backtrace<12, 1, false>();
|
||||
{
|
||||
std::unique_lock<std::mutex> _lk{ bundles_mutex };
|
||||
if(comp::roctracer::is_setup())
|
||||
+5
-59
@@ -86,7 +86,7 @@ check_error(rsmi_status_t ec)
|
||||
}
|
||||
|
||||
std::atomic<State>&
|
||||
get_rocm_smi_state()
|
||||
get_state()
|
||||
{
|
||||
static std::atomic<State> _v{ State::PreInit };
|
||||
return _v;
|
||||
@@ -151,7 +151,7 @@ config()
|
||||
void
|
||||
sample()
|
||||
{
|
||||
if(get_rocm_smi_state() != State::Active) return;
|
||||
if(rocm_smi::get_state() != State::Active) return;
|
||||
|
||||
for(auto itr : data::device_list)
|
||||
{
|
||||
@@ -168,63 +168,9 @@ sample()
|
||||
void
|
||||
set_state(State _v)
|
||||
{
|
||||
get_rocm_smi_state().store(_v);
|
||||
rocm_smi::get_state().store(_v);
|
||||
}
|
||||
|
||||
/*
|
||||
void
|
||||
data::poll(std::atomic<State>* _state, nsec_t _interval, promise_t* _ready)
|
||||
{
|
||||
threading::set_thread_name("omni.rocm_smi");
|
||||
|
||||
// notify thread started
|
||||
if(_ready) _ready->set_value();
|
||||
|
||||
std::vector<std::unique_ptr<bundle_t>*> _bundle_data{};
|
||||
_bundle_data.resize(device_count, nullptr);
|
||||
for(size_t i = 0; i < device_count; ++i)
|
||||
{
|
||||
if(device_list.count(i) > 0)
|
||||
{
|
||||
_bundle_data.at(i) = &sampler_instances::instances().at(i);
|
||||
if(!*_bundle_data.at(i)) *_bundle_data.at(i) = std::make_unique<bundle_t>();
|
||||
}
|
||||
}
|
||||
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(
|
||||
get_verbose() > 0 || get_debug(),
|
||||
"Polling rocm-smi for %zu device(s) at an interval of %f seconds...\n",
|
||||
device_list.size(),
|
||||
std::chrono::duration_cast<std::chrono::duration<double>>(_interval).count());
|
||||
|
||||
get_initial().resize(device_count);
|
||||
for(auto itr : device_list)
|
||||
get_initial().at(itr).sample(itr);
|
||||
|
||||
auto _now = std::chrono::steady_clock::now();
|
||||
while(_state && _state->load() != State::Finalized && get_state() != State::Finalized)
|
||||
{
|
||||
std::this_thread::sleep_until(_now);
|
||||
if(_state->load() != State::Active) continue;
|
||||
for(auto itr : device_list)
|
||||
{
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(),
|
||||
"Polling rocm-smi for device %u...\n", itr);
|
||||
auto& _data = *_bundle_data.at(itr);
|
||||
if(!_data) continue;
|
||||
_data->emplace_back(data{ itr });
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), " %s\n",
|
||||
TIMEMORY_JOIN("", _data->back()).c_str());
|
||||
}
|
||||
while(_now < std::chrono::steady_clock::now())
|
||||
_now += _interval;
|
||||
}
|
||||
OMNITRACE_CONDITIONAL_BASIC_PRINT(get_debug(), "Polling rocm-smi completed...\n");
|
||||
|
||||
if(polling_finished) polling_finished->set_value();
|
||||
}
|
||||
*/
|
||||
|
||||
std::vector<data>&
|
||||
data::get_initial()
|
||||
{
|
||||
@@ -236,7 +182,7 @@ bool
|
||||
data::setup()
|
||||
{
|
||||
perfetto_counter_track<data>::init();
|
||||
set_state(State::PreInit);
|
||||
rocm_smi::set_state(State::PreInit);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -244,7 +190,7 @@ bool
|
||||
data::shutdown()
|
||||
{
|
||||
OMNITRACE_DEBUG("Shutting down rocm-smi...\n");
|
||||
set_state(State::Finalized);
|
||||
rocm_smi::set_state(State::Finalized);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2022 Advanced Micro Devices, Inc. All Rights Reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/components/user_region.hpp"
|
||||
#include "library/api.hpp"
|
||||
#include "library/components/fwd.hpp"
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace component
|
||||
{
|
||||
void
|
||||
user_region::start()
|
||||
{
|
||||
if(m_prefix) omnitrace_push_region_hidden(m_prefix);
|
||||
}
|
||||
|
||||
void
|
||||
user_region::stop()
|
||||
{
|
||||
if(m_prefix) omnitrace_pop_region_hidden(m_prefix);
|
||||
}
|
||||
|
||||
void
|
||||
user_region::set_prefix(const char* _prefix)
|
||||
{
|
||||
m_prefix = _prefix;
|
||||
}
|
||||
} // namespace component
|
||||
} // namespace omnitrace
|
||||
|
||||
TIMEMORY_INITIALIZE_STORAGE(omnitrace::component::user_region)
|
||||
TIMEMORY_INSTANTIATE_EXTERN_COMPONENT(omnitrace_user_region, false, void)
|
||||
@@ -150,6 +150,12 @@ configure_settings()
|
||||
"Enable support for Kokkos Tools", false, "kokkos",
|
||||
"backend");
|
||||
|
||||
#if defined(TIMEMORY_USE_OMPT)
|
||||
OMNITRACE_CONFIG_SETTING(bool, "OMNITRACE_USE_OMPT",
|
||||
"Enable support for OpenMP-Tools", true, "openmp", "ompt",
|
||||
"backend");
|
||||
#endif
|
||||
|
||||
OMNITRACE_CONFIG_SETTING(size_t, "OMNITRACE_INSTRUMENTATION_INTERVAL",
|
||||
"Instrumentation only takes measurements once every N "
|
||||
"function calls (not statistical)",
|
||||
@@ -736,6 +742,17 @@ get_use_kokkosp()
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
}
|
||||
|
||||
bool
|
||||
get_use_ompt()
|
||||
{
|
||||
#if defined(TIMEMORY_USE_OMPT)
|
||||
static auto _v = get_config()->find("OMNITRACE_USE_OMPT");
|
||||
return static_cast<tim::tsettings<bool>&>(*_v->second).get();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
get_critical_trace_debug()
|
||||
{
|
||||
@@ -956,6 +973,20 @@ get_state()
|
||||
return _v;
|
||||
}
|
||||
|
||||
State
|
||||
set_state(State _n)
|
||||
{
|
||||
auto _o = get_state();
|
||||
OMNITRACE_CONDITIONAL_PRINT_F(get_debug_init(), "Setting state :: %s -> %s\n",
|
||||
std::to_string(_o).c_str(), std::to_string(_n).c_str());
|
||||
// state should always be increased, not decreased
|
||||
OMNITRACE_CI_BASIC_THROW(_n < _o,
|
||||
"State is being assigned to a lesser value :: %s -> %s",
|
||||
std::to_string(_o).c_str(), std::to_string(_n).c_str());
|
||||
get_state() = _n;
|
||||
return _o;
|
||||
}
|
||||
|
||||
std::atomic<uint64_t>&
|
||||
get_cpu_cid()
|
||||
{
|
||||
+3
-4
@@ -22,10 +22,9 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
// used by Kokkos decls
|
||||
#if !defined(TIMEMORY_LIBRARY_SOURCE)
|
||||
# define TIMEMORY_LIBRARY_SOURCE 1
|
||||
#endif
|
||||
#include "library/defines.hpp"
|
||||
|
||||
#define TIMEMORY_KOKKOSP_POSTFIX OMNITRACE_PUBLIC_API
|
||||
|
||||
#include "library/components/omnitrace.hpp"
|
||||
#include "library/config.hpp"
|
||||
@@ -0,0 +1,114 @@
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) 2020, The Regents of the University of California,
|
||||
// through Lawrence Berkeley National Laboratory (subject to receipt of any
|
||||
// required approvals from the U.S. Dept. of Energy). All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
#include "library/defines.hpp"
|
||||
|
||||
#include <timemory/defines.h>
|
||||
|
||||
#if defined(TIMEMORY_USE_OMPT)
|
||||
|
||||
# include "library/components/fwd.hpp"
|
||||
# include "library/components/user_region.hpp"
|
||||
# include "library/config.hpp"
|
||||
# include "library/debug.hpp"
|
||||
|
||||
# include <timemory/components/ompt.hpp>
|
||||
# include <timemory/components/ompt/extern.hpp>
|
||||
# include <timemory/timemory.hpp>
|
||||
|
||||
# include <memory>
|
||||
|
||||
using api_t = TIMEMORY_API;
|
||||
using ompt_handle_t = tim::component::ompt_handle<api_t>;
|
||||
using ompt_context_t = tim::openmp::context_handler<api_t>;
|
||||
using ompt_toolset_t = typename ompt_handle_t::toolset_type;
|
||||
using ompt_bundle_t = tim::component_tuple<ompt_handle_t>;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
ompt_start_tool_result_t* ompt_start_tool(unsigned int,
|
||||
const char*) OMNITRACE_PUBLIC_API;
|
||||
}
|
||||
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace ompt
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::unique_ptr<ompt_bundle_t> f_bundle = {};
|
||||
bool _init_toolset_off = (trait::runtime_enabled<ompt_toolset_t>::set(false), true);
|
||||
} // namespace
|
||||
|
||||
void
|
||||
setup()
|
||||
{
|
||||
OMNITRACE_VERBOSE(1, "Setting up OMPT...\n");
|
||||
trait::runtime_enabled<ompt_toolset_t>::set(config::get_use_ompt());
|
||||
comp::user_ompt_bundle::global_init();
|
||||
comp::user_ompt_bundle::reset();
|
||||
// provide environment variable for enabling/disabling
|
||||
if(config::get_use_ompt())
|
||||
{
|
||||
tim::auto_lock_t lk{ tim::type_mutex<ompt_handle_t>() };
|
||||
comp::user_ompt_bundle::configure<omnitrace::component::user_region>();
|
||||
f_bundle =
|
||||
std::make_unique<ompt_bundle_t>("ompt", quirk::config<quirk::auto_start>{});
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shutdown()
|
||||
{
|
||||
OMNITRACE_VERBOSE(1, "Shutting down OMPT...\n");
|
||||
if(f_bundle)
|
||||
{
|
||||
f_bundle->stop();
|
||||
ompt_context_t::cleanup();
|
||||
trait::runtime_enabled<ompt_toolset_t>::set(false);
|
||||
}
|
||||
f_bundle.reset();
|
||||
}
|
||||
} // namespace ompt
|
||||
} // namespace omnitrace
|
||||
|
||||
// include the ompt_start_tool definition
|
||||
# include <timemory/components/ompt/start_tool.hpp>
|
||||
|
||||
#else
|
||||
namespace omnitrace
|
||||
{
|
||||
namespace ompt
|
||||
{
|
||||
void
|
||||
setup()
|
||||
{}
|
||||
|
||||
void
|
||||
shutdown()
|
||||
{}
|
||||
} // namespace ompt
|
||||
} // namespace omnitrace
|
||||
|
||||
#endif
|
||||
Certains fichiers ne sont pas affichés car ce diff contient trop de modifications Voir plus
Référencer dans un nouveau ticket
Bloquer un utilisateur